AtCoder Beginner Contest 280 ABCDE

发布时间 2023-06-28 22:34:59作者: nannan4128

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;
}