Codeforces Round #736 (Div. 2)
A. Gregor and Cryptography
- 题意
给出一个p, 让你找到x,y令 (x%p = y%p)
- 思路
签到思维,想一下mod p = 1的情况就行
code :
void solve(){
int n;
cin >> n;
if(n == 5) {
cout << "2 4" << endl;
return;
}
cout << "2 " << n / 2 << endl;
}
B. Gregor and the Pawn Game
- 题意
给一个棋盘,给出的第一行是敌人的,第二行是自己的,敌人不动,我们自己可以进行两个操作
- 当上方的没有敌人的棋子,直接占用即可
- 当敌人的棋子在左上或右上的时候,可以选择移至敌人的棋子位子,并吃掉它
- 思路
贪心, 优先拿左边的,中间的,右边的,记录一下是否用过即可
code :
char a[N], b[N];
bool st[N];
void solve(){
int n;
cin >> n;
for(int i = 1;i <= n;i ++ ) st[i] = 0;
cin >> (a + 1) >> (b + 1);
int ans = 0;
for(int i = 1;i <= n;i ++) {
if(a[i] == '1') {
if(b[i - 1] == '1' && !st[i - 1]) ans ++;
else if(i + 1 <= n && b[i + 1] == '1') {
ans ++;
st[i + 1] = 1;
}
}else if(b[i] == '1' && !st[i]) {
ans ++;
st[i] = 1;
}
}
cout << ans << endl;
}
C. Web of Lies
- 题意
给出一个图,每个人及一个点,且当前点的权值为它自己的编号((w_i = i)),当一个人相连的另一个人的权值大于他时,他会死,求最后剩下几个人
三种操作
- 增加一条边((u o v))
- 删除一条边((u o v)), 保证存在
- 查询当前剩下几个人
- 思路
建边后,记录每个人相邻的人中有多少个大于他本身的点,那么只有当所有大于他权值的点和他连的边全删了,他才能活,这里用set进行处理删除和增加边的操作,O(logn)
code :
int st[N];
void solve(){
int n,m;
cin >> n >> m;
for(int i = 1;i <= n;i ++) st[i] = 0;
int ans = n;
while(m --) {
int a,b;
cin >> a >> b;
if(a > b) swap(a,b);
if(!st[a]) {
ans --;
}
st[a]++;
}
int k;
cin >> k;
fep(i,1,k) {
int op;
cin >> op;
if(op == 1) {
int a,b;
cin >> a >> b;
if(a > b) swap(a,b);
if(!st[a]) {
ans --;
}
st[a]++;
}else if(op == 2) {
int a,b;
cin >> a >> b;
if(a > b) swap(a,b);
st[a] --;
if(!st[a]) ans ++;
}else {
cout << ans << endl;
}
}
}
D. Integers Have Friends
- 题意
给出一个长度为 n 的序列,让你求一个最大长度的连续子序列中 (a_i mod m = a_{i + 1} mod m = ···· a_j mod m) , (i -> j), 输出最大的长度
- 思路
发现差分数组中,某个区间的gcd != 1时,那么这个区间是可以的,那么更新答案。
用st表处理区间gcd,双指针处理左右端点 或 枚举左端点二分长度来处理区间都行。
code :
// ST表处理
int lg[N]; // lg函数记录(int)log(i)
int st[30][N]; // st表,计算st[len][l]的最小值的下标
int n;
int a[N], b[N];
// 处理
void buildST() {
fep(i,2,n - 1) lg[i]=lg[i >> 1] + 1;
fep(i,1,n - 1) st[0][i] = b[i];
fep(j,1,lg[n - 1]) // 长度
for(int i = 1;i < n - (1 << j) + 1;i ++){ // 左端点
st[j][i] = __gcd(st[j - 1][i],st[j - 1][i + (1 << (j - 1))]);
}
}
int get_(int l,int r) {
int len = lg[r - l + 1];
return __gcd(st[len][l],st[len][r - (1 << len) + 1]);
}
void solve(){
cin >> n;
fep(i,1,n) cin >> a[i];
if(n == 1) {
cout << "1" << endl;
return;
}
fep(i,1,n - 1) b[i] = abs(a[i + 1] - a[i]);
buildST();
int ans = 1;
int j = 1;
for (int i = 1; i < n; ++i){
while(j <= i && get_(j,i) == 1) j ++;
ans = max(ans, i - j + 2);
}
cout << ans << endl;
}