AtCoder Beginner Contest 300 (A~F)

A - N-choice question

题意:找A+B对应的i

思路:水

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int n,a,b;cin >> n >> a >> b;
	for(int i = 1;i <= n;i++){
		int c;cin >> c;
		if(a+b == c){
			cout << i;
			break;
		}
	}
}

B - Same Map in the RPG World

题意:给出两个只由’.‘和’#',长宽均分别为H,W的图,每次操作可以横向全图向左移动,或向下移动,问能否经过任意次数将图A变成图B

思路:数据量较小,因此枚举移动次数即可,并且无论顺序如何,只要次数一定,那么最后变成的图是不变的

#include<bits/stdc++.h>
using namespace std;
bool a[31][31],b[31][31];
int main()
{
	int h,w;cin >> h >> w;
	for(int i = 1;i <= h;i++){
		string str;cin >> str;
		for(int j = 0;j < w;j++){
			if(str[j] == '.')
				a[i][j + 1] = 1;
		}
	}
	for(int i = 1;i <= h;i++){
		string str;cin >> str;
		for(int j = 0;j < w;j++){
			if(str[j] == '.')
				b[i][j + 1] = 1;
		}
	}
	bool f = 0;
	for(int i = 0;i < h;i++)
	for(int j = 0;j < w;j++){
		bool ff = 1;
		for(int _i = 1;_i <= h;_i++)
		for(int _j = 1;_j <= w;_j++){
			if(a[(_i + i - 1) % h + 1][(_j + j - 1) % w + 1] != b[_i][_j])
				ff = 0;
		}
		f |= ff;
	}
	if(f)
		cout << "Yes" << endl;
	else
		cout << "No" << endl;
}

C - Cross

题意:一个图,找所有大小的斜向十字的数量

思路:暴力枚举所有点为中心

#include<bits/stdc++.h>
using namespace std;
bool c[101][101];
int h,w;
int num[101];
int f(int i,int j){
	int t = 1;
	while(i + t <= h && i - t >= 1 && j + t <= w && j - t >= 1 && c[i+t][j+t] && c[i+t][j-t] && c[i - t][j + t] && c[i - t][j - t]){
		c[i+t][j+t] = c[i+t][j-t] = c[i-t][j-t] = c[i - t][j + t] = 0;
		t++;
	}
	return t - 1;
}
int main()
{
	cin >> h >> w;
	for(int i = 1;i <= h;i++)
	{
		string str;cin >> str;
		for(int j = 0;j < w;j++){
			if(str[j] != '.')
				c[i][j + 1] = 1;
		}
	}
	for(int i = 1;i <= h;i++)
	for(int j = 1;j <= w;j++)
		if(c[i][j])
			num[f(i,j)]++;
	int mi = min(h,w);
	for(int i = 1;i <= mi;i++)
		cout << num[i] << ' ';
}

D - AABCC

题意:找所有 a 2 b c 2 < = n ( a < b < c ) a^2bc^2<=n(a<b<c) a2bc2<=n(a<b<c)并且 a , b , c a,b,c a,b,c均为素数, n < = 1 0 12 n<=10^{12} n<=1012

思路: a 2 b c 2 < = n a^2bc^2<=n a2bc2<=n,因此 c < = n c<=\sqrt{n} c<=n ,因此只要枚举 [ 2 , 1 0 6 ] [2,10^{6}] [2,106]的素数即可,先枚举a,然后枚举c,然后二分找b的范围, b < = n / ( a 2 c 2 ) b<=n/(a^2c^2) b<=n/(a2c2)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int max_range = 1e6 + 10;
bool prime[max_range];
vector<ll> pm;
void pre_prime(){
	for(int i = 2;i < max_range;i++)
	{
		if(!prime[i])
		{
			pm.push_back(i);
			for(int j = 2;j*i < max_range;j++)
				prime[i*j] = 1;
		}
	}
}
int main()
{
	ll n;cin >> n;
	ll ans = 0;
	pre_prime();
	int ma = pm.size();
	for(int i = 0;i < ma;i++)//枚举a
	{
		if(n/pm[i]/pm[i]/pm[i+2]/pm[i+2]/pm[i+1] == 0)
			break;
		for(int j = i + 2;j < ma;j++){//枚举c
			ll x = n/pm[i]/pm[i]/pm[j]/pm[j];
			int aim = lower_bound(pm.begin(),pm.end(),x) - pm.begin();
			if(pm[i]*pm[i]*pm[j]*pm[j]*pm[aim] > n)
				aim--;
			if(aim < i + 1)
				break;
			else
				ans += min(aim - i,j - 1 - i);
		}
	}
	cout << ans << endl;
}

E - Dice Product 3

题意:一开始的数字为1,每次投出 [ 1 , 6 ] [1,6] [1,6]的骰子,然后数字乘上这个数,直到大于等于给定的数字n,问正好为n的可能性为多少

思路:分解n为2、3、4、5、6,因为6会被分解为2和3,4会被分解为2,所以我们要枚举4和6的数量,确定了2、3、4、5、6的数量后,可能性就要加上 A n u m a l l n u m a l l / ( 5 n u m a l l A n u m 2 n u m 2 A n u m 3 n u m 3 A n u m 4 n u m 4 A n u m 5 n u m 5 A n u m 6 n u m 6 ) A^{num_{all}}_{num_{all}}/(5^{num_{all}}A^{num_2}_{num_2}A^{num_3}_{num_3}A^{num_4}_{num_4}A^{num_5}_{num_5}A^{num_6}_{num_6}) Anumallnumall/(5numallAnum2num2Anum3num3Anum4num4Anum5num5Anum6num6)

#include<bits/stdc++.h>
using namespace std;
 
typedef long long ll;
const ll MAXN = 1000001;
ll ny[MAXN],p = 998244353;
ll jcny[MAXN],jc[MAXN];
void pre_ny()//预处理逆元
{
    ny[1] = 1;
    for(ll i = 2;i <= MAXN;i++)
        ny[i] = ((p - p / i) * ny[p % i]) % p;
}
void pre_jcny()//预处理阶乘的逆元
{
    jcny [0] = jcny[1] = 1;
    for(ll i = 2;i <= MAXN;i++)
        jcny[i] = jcny[i - 1] * ny[i] % p;
}
void pre_jc()//预处理阶乘
{
    jc[0] = jc[1] = 1;
    for(ll i = 2;i <= MAXN;i++)
        jc[i] = jc[i - 1] * i % p;
}
ll C(ll a,ll b)//计算组合数
{
    return (jc[a] * jcny[a - b] % p * jcny[b] % p) % p;
}
ll fmx(ll x,ll y){
	ll ans = 1;
	while(y){
		if(y&1) ans = (ans*x) % p;
		x = (x*x) % p;
		y >>= 1;
	}
	return ans;
}
ll num[7];
int main()
{
	pre_ny();
	pre_jc();
	pre_jcny();
	ll n;cin >> n;
	ll ans = 0;
	for(int i = 2;i <= 5;i++){
		while(n % i == 0)
		{
			n /= i;
			num[i]++;
		}
	}
	if(n != 1){
		cout << 0;
		return 0;
	}
	int mi = min(num[2],num[3]);
	for(int j = 0;j <= mi;j++)//枚举6的数量
	{
		int left_2 = num[2] - j;//剩余2的数量
		int left_3 = num[3] - j;
		for(int i = 0;left_2 - 2*i >= 0;i++)//枚举4的数量
		{
			ll nyy = (((((((((jcny[num[5]]*jcny[left_2 - 2*i]) % p) * jcny[left_3])%p)*jcny[i])%p)*jcny[j]) % p)*fmx(fmx(5,p-2),num[5] + left_2 - 2*i + i + left_3 + j)) % p;
			ans = (ans + (((jc[num[5] + left_2 - 2*i + i + left_3 + j] * nyy) % p))) % p;
		}
	}
	cout << ans;
}

F - More Holidays

题意:给出只由’x’和’o’组成的字符串S,然后用m个S相连组成字符串T,先从T中将k个’x’变成’o’,问最长连续的’o’的长度为多少。

思路:要让o最长,那么k个将’x’变成’o’的机会都肯定用在这个串中,因此如果这个串经过了好几个S,那么S里面的x都会变成o,我们用一个串的x的数量除上k,就得到了最多穿过的区间, k % = n u m k\%=num k%=num得到多余的数量,用双指针维护总长度,注意最大不能超过n*m

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
	ll n,m,k;cin >> n >> m >> k;
	string str;cin >> str;
	ll ans = 0,ma = 0,num = 0,end = 0;
	for(;end < n;end++){
		if(str[end] == 'x')
			num++;
	}
	ll block = k / num;//跨越了几个区间
	ans = block * n - 1;
	k %= num;
	while(k){
		ans++;
		if(str[ans % n] == 'x')
			k--;
	}
	while(str[(ans + 1) % n] != 'x')
		ans++;
	ma = min(n*m,ans + 1);
	for(int i = 1;i <= n - 1;i++){//起点向前推
		if(str[i - 1] == 'o');
		else if(str[i - 1] == 'x'){
			ans++;
			while(str[ans % n] != 'x'){
				ans++;
			}
			while(str[(ans + 1) % n] != 'x')
				ans++;
			
			ma = max(min(ans - i + 1,n*m - i + 1),ma);
		}
	}
	cout << ma << endl;
}
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值