CF1766 A-D总结

A. 简单数学

枚举每一个数字能不能出现就行了. 得到算式即可.

#include <bits/stdc++.h>
using namespace std;
void solve(){
	string s; cin>>s;
	int sz = s.size();
	int dig = (s[0]-'0');
	cout<<sz*9-(9-dig)<<endl;
}
int main(){
	int T; cin>>T; while(T--) solve();
}

B. 枚举

转化为是不是有一个已经出现过的长度至少为2的字串. 因此用lst数组(last)表示最远的那一个是在哪, 然后根据当前的情况决定是不是可以继续循环.

#include <bits/stdc++.h>
#define F(i, a, b) for(int i=a; i<=b;i++)
#define Fd(i, b, a) for(int i=b; i>=a; i--)
#define MAGIC 11451419
using namespace std;
int lst[250][250];
bool solve(){
	F(i, 0, 199) F(j, 0, 199) lst[i][j]=MAGIC;
	int n; cin>>n; 
	string s; cin>>s;
	for(int i=0; i<n-1; i++){
		if(lst[s[i]][s[i+1]]==MAGIC)lst[s[i]][s[i+1]]=min(i,lst[s[i]][s[i+1]]);
		else{
			if(lst[s[i]][s[i+1]]==(i-1) ) continue; //第一次在这里错了
			else return 1; 
		}
	}
	return 0;
}
int main(){
	int T; cin>>T; while(T--) if(solve())cout<<"Yes\n";else cout<<"No\n";
}

C. 观察

注意到只有

.##   .##.  ...   ###
##.   ####  ###   ...

并且每一次竖着变换一次之后上下的延申可以改变. 因此有代码:

#include <bits/stdc++.h>
#define F(i, a, b) for(int i=a; i<=b;i++)
#define Fd(i, b, a) for(int i=b; i>=a; i--)
#define GET(x) (x=='B'?1:0)
#define BLACK 1
#define WHITE 0
#define MAXN 200010
#define pb push_back 
using namespace std;
int a[MAXN], b[MAXN];
vector<int> v;
bool sol(){
	v.clear();
	int n; cin>>n;
	string s; cin>>s; string t; cin>>t;
	F(i, 1, n){
		a[i] = GET(s[i-1]);
	}
	F(i, 1, n){
		b[i] = GET(t[i-1]);
	}
	v.pb(0);
	F(i, 1, n){
		if(a[i]==1 && b[i]==1){
			v.pb(i);
		}
	}
	v.pb(n+1);
	#define UP 0
	#define DOWN 1
	#define UNDEF -1
	#define ISATUP(x) (a[x]==BLACK)
	#define ISATDOWN(x) (b[x]==BLACK)
	int lvl=UNDEF;
	int sz=v.size();
	F(i, 0, sz-2){
		if(v[i]-v[i+1]<=1) {
			if(v[i]-v[i+1]==0)continue;
			else if(v[i]-v[i+1]==1){
				lvl = lvl^1;continue;
			}
		}
		if(lvl != UNDEF) lvl ^=1;
		int start = v[i]+1;
		int end = v[i+1]-1;
		F(j, start, end){
//			printf("Examine %d..%d\n", start, end);
			if(lvl==UNDEF){
				if(ISATUP(j)) lvl = UP;
				else lvl=DOWN;
			}else{
				if(ISATUP(j) && lvl==DOWN) return 0;
				if(ISATDOWN(j) && lvl==UP) return 0;
			}
		}
	}
	return 1;
}
int main(){
	int T; cin>>T; while(T--) if(sol())cout<<"Yes\n";else cout<<"No\n";
	
}

D. gcd的简单性质

原来的想法: 记录二者之间的差值k, 然后从(0,k)开始找到一个距离当前最近的然后统计后续的内容
问题: 比较麻烦并且质因数的位置不是很好处理.

考虑转化为 \(\gcd(x+k,y-x)=1\), 当 \(y-x\) 时输出 -1, 否则发现,\(\gcd(x+k,y-x)\ne1\),与 \(x-k\)\(y−x\) 的某个质因子的倍数这两句话等价. 而 \(y-x\le10^7\), 提前筛出来, 处理询问的时候枚举每个质因子, 并找到每个质因子的最小的倍数 d, 满足 \(d\ge x\), 并更新答案即可.

posted @ 2022-12-18 14:49  Micoael_Primo  阅读(26)  评论(0)    收藏  举报