• Codeforces Round #779 (Div. 2)


    CF1658A Marin and Photoshoot

    任意两个 0 之间至少有两个 1,不够就补上。

    char s[MAXN];
    
    int main() {
    	int T;
    	read(T);
    	while(T -- > 0) {
    		int n;read(n);
    		scanf("%s" , s + 1);
    		int ans = 0;
    		for (int i = 1; i < n; ++i) if(s[i] == '0') {
    			if(s[i + 1] == '0') ans += 2;
    			else if(s[i + 2] == '0') ans ++;
    		}
    		write(ans);
    	}
    	return 0;
    }
    

    CF1658B Marin and Anti-coprime Permutation

    说真的,很有意思。

    人类思维:明显有特解,奇数放偶位,偶数放奇位,观察样例发现很可能是充分必要条件。

    于是尝试推广,设 \(\gcd\)\(x\) ,则 \([1,n]\) 中是 \(x\) 倍数的有 \(\lfloor \frac{n}{x} \rfloor\) 个。

    然后因此 \(x > 2\) 时我们肯定无法让每个位置都被 \(x\) 整除,于是之前的观察很对。

    const int mod = 998244353;
    
    int main() {
    	int T;
    	read(T);
    	while(T -- > 0) {
    		int n;read(n);
    		if(n & 1) {
    			puts("0");
    			continue;
    		}
    		LL ans = 1;
    		for (int i = 1; i <= n / 2; ++i) ans = ans * i % mod;
    		ans = ans * ans % mod;
    		write(ans);
    	}
    	return 0;
    }
    

    CF1658C Shinju and the Lost Permutation

    同样是观察,发现有特殊情况。即当最大值在最前面的时候 b1

    之后继续循环位移,发现一次最多增加 1 或者减少很多,发现如果满足该性质我一定能通过建立拓扑序构造解,因此又是一个充分必要条件,模拟一下就好。

    const int MAXN = 2e5 + 5;
    
    int c[MAXN] , n;
    
    int main() {
    	int T;
    	read(T);
    	while(T -- > 0) {
    		read(n);
    		int num = 0;
    		for (int i = 1; i <= n; ++i) read(c[i]),c[i + n] = c[i] , num += (c[i] == 1);
    		if(num != 1) {
    			puts("NO");
    			continue;
    		}
    		for (int i = 1; i <= n; ++i) if(c[i] == 1) num = i;
    		int fl = 1;
    		for (int i = 1; i < n; ++i) if(c[i + num] - c[i + num - 1] > 1) {
    			fl = 0;
    			break;
    		}
    		if(fl) puts("YES");
    		else puts("NO");
    	}
    	return 0;
    }
    

    CF1658D

    没考虑过 D1 的特别做法,直接做的通解。

    \([l,r]\) 是排列的一部分,所以互不相同,异或上一个数后还是互不相同。

    考虑我得到的序列,枚举哪个数字是 \(l\) 变化过来的,于是就能枚举到 \(x\) ,由于给定数互不相同,所以异或上 \(x\) 也互不相同,只要保证这些数异或上 \(x\) 的最小值是 \(l\) ,最大值是 \(r\) 就好了。

    具体用 01-trie 实现。

    const int MAXN = (1 << 17) + 5;
    
    int num , ch[MAXN * 17][21];
    void Insert(int x) {
    	int cur = 1;
    	for (int i = 16; i >= 0; --i) {
    		int k = (x >> i) & 1;
    		if(!ch[cur][k]) ch[cur][k] = ++num;
    		cur = ch[cur][k];
    	}
    }
    
    int calc(int x , int ty) {
    	int cur = 1 , ans = 0;
    	for (int i = 16; i >= 0; --i) {
    		int k = (x >> i) & 1;
    		if(ch[cur][k ^ ty]) {
    			cur = ch[cur][k ^ ty];
    			ans += (ty) << i;
    		}
    		else if(ch[cur][k ^ ty ^ 1]) {
    			cur = ch[cur][k ^ ty ^ 1];
    			ans += (ty ^ 1) << i;
    		} 
    		else break;
    	}
    	return ans;
    }
    
    int a[MAXN];
    
    int main() {
    	int T;
    	read(T);
    	while(T -- > 0) {
    		num = 1;int l , r;
    		read(l),read(r);
    		for (int i = 1; i <= r - l + 1; ++i) {
    			read(a[i]);
    			Insert(a[i]);
    		}
    		for (int i = 1; i <= r - l + 1; ++i) {
    			int x = a[i] ^ l;
    			if(calc(x , 0) == l && calc(x , 1) == r) {
    				write(x);
    				break;
    			}
    		}
    		for (int i = 1; i <= num; ++i) ch[i][0] = ch[i][1] = 0;
    	}
    	return 0;
    }
    

    CF1658E Gojou and Matrix Game

    一个数开始,如果不能走到一个比它大的数,那先手必胜,否则看能否一步走到先手必胜点。

    于是从大到小枚举转移,判断能否到达比它大的先手必胜点。

    具体用曼哈顿转切比雪夫,用树状数组维护切比雪夫坐标。

    const int N = 8000;
    const int C = 4000;
    
    int v[2005][2005] , ans[2005][2005];
    pii pos[2005 * 2005];
    
    struct BIT {	
    	int tr[N + 5];
    	void update(int x , int y) {for (; x <= N; x += (x & (-x))) tr[x] += y;}
    	int find(int x) {int res = 0;for (; x; x -= (x & (-x))) res += tr[x];return res;}
    }T[2];
    
    int main() {
    	int n , k;
    	read(n),read(k);
    	for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) read(v[i][j]) , pos[v[i][j]] = mp(i , j);
    	
    	for (int i = n * n; i >= 1; --i) {
    		int X = pos[i].fs + pos[i].sc , Y = pos[i].fs - pos[i].sc + C;
    		
    		int cur = 0;
    		if(X - k - 1 >= 1) cur += T[0].find(X - k - 1);
    		if(X + k + 1 <= N) cur += T[0].find(N) - T[0].find(X + k);
    		if(Y - k - 1 >= 1) cur += T[1].find(Y - k - 1);
    		if(Y + k + 1 <= N) cur += T[1].find(N) - T[1].find(Y + k);
    		
    		if(!cur) ans[pos[i].fs][pos[i].sc] = 1 , T[0].update(X , 1) , T[1].update(Y , 1); 	
    	}
    	
    	for (int i = 1; i <= n; ++i , puts("")) for (int j = 1; j <= n; ++j) {
    		if(ans[i][j]) putchar('M');
    		else putchar('G');
    	}
    	
    	return 0;
    }
    

    CF1658F Juju and Binary String

    更加厉害的观察题。

    有无解很好判断。观察从每个数开始后面 \(m\) 个数的 1 的个数,记为 \(c_i\)(将序列视为环),则 \(c_i\) 每次变化量为 \(1\)。则必有 \(c_i = m\)

    因此只用最多两步完成构造。

    const int MAXN = 4e5 + 5;
    
    int n , m , c[MAXN];
    char s[MAXN];
    
    int main() {
    	int T;
    	read(T);
    	while(T -- > 0) {
    		read(n),read(m);
    		scanf("%s" , s + 1);
    		LL num = 0;
    		for (int i = 1; i <= n; ++i) {
    			s[i + n] = s[i];
    			num += (s[i] - '0');
    		}
    		if(num * m % n != 0) {
    			puts("-1");
    			continue;
    		}
    		c[n + 1] = 0;
    		for (int i = 1; i <= m; ++i) c[n + 1] += s[i] - '0';
    		for (int i = n; i >= 1; --i) c[i] = c[i + 1] + (s[i] - '0') - (s[i + m] - '0');
    		for (int i = 1; i <= n; ++i) {
    			if(c[i] == num * m / n) {
    				if(i + m - 1 <= n) {
    					puts("1");
    					write(i , ' ') , write(i + m - 1);
    				}
    				else {
    					puts("2");
    					write(1 , ' ') , write(i + m - 1 - n);
    					write(i , ' ') , write(n);
    				}
    				break;
    			}
    		}
    		
    	}
    	return 0;
    }
    
  • 相关阅读:
    hdu 1025 lis 注意细节!!!【dp】
    简单的数据生成方法
    注意特殊情况!最长上升子序列!!poj2533
    括号序列问题 uva 1626 poj 1141【区间dp】
    UVa 10502【dp】
    hdu 1024 MAX Sum Plus Plus【dp】
    python 《核心编程》 1,2章
    c语言 文件链表实现最简单的学生管理系统
    Python和Python解释器
    计算机基础小结
  • 原文地址:https://www.cnblogs.com/Reanap/p/16079573.html
Copyright © 2020-2023  润新知