AtCoder Beginner Contest 280
A - Pawn on a Grid
Problem Statement
题意:给你\(N\)行\(M\)列的网格,问你有多少个#
Solution
思路:直接记录个数就行。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int cnt = 0;
int n,m;
cin>>n>>m;
for(int i =1;i<=n;i++)
for(int j = 1;j<=m;j++)
{
char x;
cin>>x,cnt += (x=='#');
}
cout<<cnt<<endl;
return 0;
}
B - Inverse Prefix Sum
Problem Statement
题意:给你一个前缀和数组让你求原数组
Solution
思路:差分
#include<bits/stdc++.h>
using namespace std;
const int N = 10;
long long a[N],b[N],n;
int main()
{
int n;
cin>>n;
for(int i = 1;i<=n;i++)
cin>>a[i];
for(int i = 1;i<=n;i++)
b[i] = a[i]-a[i-1];
for(int i = 1;i<=n;i++)
cout<<b[i]<<" ";
cout<<endl;
return 0;
}
C - Extra Character
Problem Statement
题意:给你两个字符串\(S\)和\(T\),问你在\(S\)哪个位置插一个字母和\(T\)一样
Solution
思路:for一遍看那个位置不一样,如果前\(len_s\)个都一样,那就插在最后
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s,t;
cin>>s>>t;
int m = t.size();
s = "?"+s,t = "?"+t;
bool ok = true;
int pos = -1;
for(int i = 1;i<=m;i++)
{
if(s[i]!=t[i])
{
ok = false;
pos = i;
break;
}
}
if(ok)cout<<m<<endl;
else cout<<pos<<endl;
return 0;
}
D - Factorial and Multiple
Problem Statement
题意:给你一个大于等于2的整数\(K\),让你找到最大的正整数\(N\)满足\(k|N!\)
Solution
思路:
由唯一分解定理可知,一个数\(n\)可以写成素数幂的乘积。
比如\(n = p_1^{e_1}p_2^{e_2}...p_k^{e_k}\)
因为\(N!\)能被\(K\)整除,说明每一项\(p_i\)的素数幂次至少有\(e_i\)个
比如:\(280 = 2^3\times 5^1 \times 7^1\)
也就是说要能整除\(280\),至少有\(3\)个\(2\),\(1\)个\(5\)和\(1\)个\(7\)
那么我们对每个素因子\(p_i\)判断,满足至少含\(e_i\)个的\(p_i\)的阶乘是几。
比如还是以\(280\)为例:
对于第一个素因子 \(p = 2\),我们分解质因数之后知道它至少要\(3\)个,\(cnt = 3\)
int p = 2,tmp = 0;
while(cnt>0)
{
tmp += p;
ll x = tmp;
while(x%p==0)x/=p,cnt--;
}
什么意思呢?
一开始\(tmp = 2\),那我们看\(2!\)有几个\(2\),我们发现有一个,那现在\(cnt\)变为\(2\),我们还需要\(2\)个\(2\),那我们继续加,\(tmp += 2\),那我们发现\(4!\)有\(2\)个\(2\),那满足了,那对于\(p = 2\)而言,答案至少是\(4!\)。
答案为什么直接就是对\(tmp\)取\(max\)呢?
因为在我们算\(4!\)之前先算了\(2!\)对吧,而\(4 = 4\times3\times2\times1\), \(2 = 2\times 1\)
很显然\(4\)的阶乘包含\(2\)的阶乘,同理大的阶乘含素数个数包含了小的,也就是说,我们算\(4!\)的贡献的时候,只需要算出\(4\)本身的贡献加上前面的\(2\)的贡献即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ll k;
cin>>k;
ll cnt = 0;
ll ans = 0;
for(int i = 2;i<=k/i;i++)
{
cnt = 0;
if(k%i==0)
while(k%i==0)cnt++,k/=i;
ll tmp = 0;
while(cnt>0)
{
tmp += i;
ll x = tmp;
while(x%i==0)
{
x/=i;
cnt--;
}
}
ans = max(ans,tmp);
}
cout<<max(ans,k)<<endl;
return 0;
}
E - Critical Hit
Problem Statement
题意:一个怪兽有\(N\)点耐力值。
一次攻击有\(\dfrac{P}{100}\)的概率使得怪兽的耐力值\(-2\),有\(1-\dfrac{P}{100}\)的概率\(-1\)
求使得怪兽耐力值减小到\(0\)以下的期望次数。用逆元,模数是\(998244353\)
Solution
思路:一个正常的概率\(dp\)
定义\(dp[i]\)为耐力值为\(i\)时候的期望次数,那显然\(dp[0] = 0,dp[1] = 1\)
因为除以\(100\),我们可以先对\(100\)求个逆元\(inv\)
状态转移:\(dp[i] = dp[i-2]*P*inv+dp[i-1]*(100-p)*inv+1\)
记得取模不要炸了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
const int mod = 998244353;
struct modular_arithmetic {
int add(ll a, ll b) {
return (a % mod + b % mod) % mod;
}
int mul(ll a, ll b) {
return ((a % mod) * (b % mod)) % mod;
}
int pow(ll x, ll n) {
if (n == 0) return 1;
int res = pow(x, n / 2);
res = mul(res, res);
if (n % 2) res = mul(x, res);
return res;
}
int inv(ll x) {
return pow(x, mod - 2);
}
int div(ll a, ll b) {
return mul(a, inv(b));
}
};
modular_arithmetic Mod;
ll n,p;
ll dp[N];
int main()
{
cin>>n>>p;
ll inv = Mod.inv(100);
dp[0] = 0 ,dp[1] = 1;
for(int i = 2;i<=n;i++)
dp[i] = (dp[i-2]*p%mod*inv%mod + dp[i-1]*(100-p+mod)%mod*inv%mod+1)%mod;
cout<<dp[n]<<endl;
return 0;
}
- Beginner AtCoder Contest ABCDE 280beginner atcoder contest abcde contest programming beginner atcoder beginner atcoder contest 296 beginner atcoder contest 295 beginner atcoder contest 335 beginner atcoder contest 328 beginner atcoder contest 334 beginner atcoder contest 332 beginner atcoder contest 327 beginner atcoder contest 315