zoukankan      html  css  js  c++  java
  • 【题解】 Codeforces Round #724 (Div. 2) 题解

    送温暖场。

    最后一题没写纯属脑抽了。

    A - Omkar and Bad Story

    不难发现有负数时一定无解。其余时候最简单的构造就是输出 (0,1,2,cdots,200)

    时间复杂度 (O(n))

    code
    #include <bits/stdc++.h>
    
    const int MX = 1e5 + 23;
    
    void solve(){
    	int n; std::cin >> n;
    	int ok = 1;
    	for(int i = 1 ,r = 0; i <= n ; ++i){
    		std::cin >> r;
    		if(r < 0) ok = 0;
    	}
    	if(!ok){
    		puts("NO");
    		return ;
    	}
    	puts("YES
    201");
    	for(int i = 0 ; i <= 200 ; ++i)
    		printf("%d%c" ,i ," 
    "[i == 200]);
    }
    
    int main(){
    	int T;
    	std::cin >> T;
    	while(T--) solve();
    	return 0;
    }
    
    

    B - Prinzessin der Verurteilung

    只会暴力,显然字符串长度不会超过 (3),且长度为 (n) 的字符串最多有 (O(n^2)) 个不同子串,直接枚举即可。

    时间复杂度 (O(n^2))

    code
    #include <bits/stdc++.h>
    
    const int MX = 1e5 + 23;
    
    char ok1[26][26][26];
    char ok2[26][26];
    char ok3[26];
    
    void solve(){
    	int n; std::cin >> n;
    	std::string s; std::cin >> s;
    	
    	for(int i = 0 ; i < n ; ++i){
    		ok3[s[i] - 'a'] = 1;
    		if(i >= 1) ok2[s[i - 1] - 'a'][s[i] - 'a'] = 1;
    		if(i >= 2) ok1[s[i - 2] - 'a'][s[i - 1] - 'a'][s[i] - 'a'] = 1;
    	}
    	
    	for(int i = 0 ; i < 26 ; ++i){
    		if(!ok3[i]){
    			printf("%c
    " ,'a' + i);
    			goto end;
    		}
    	}
    	for(int i = 0 ; i < 26 ; ++i){
    		for(int j = 0 ; j < 26 ; ++j){
    			if(!ok2[i][j]){
    				printf("%c%c
    " ,'a' + i ,'a' + j);
    				goto end;
    			}
    		}
    	}
    	for(int i = 0 ; i < 26 ; ++i){
    		for(int j = 0 ; j < 26 ; ++j){
    			for(int k = 0 ; k < 26 ; ++k){
    				if(!ok1[i][j][k]){
    					printf("%c%c%c
    " ,'a' + i ,'a' + j ,'a' + k);
    					goto end;
    				}
    			}
    		}
    	}
    	
    	end:
    	for(int i = 0 ; i < n ; ++i){
    		ok3[s[i] - 'a'] = 0;
    		if(i >= 1) ok2[s[i - 1] - 'a'][s[i] - 'a'] = 0;
    		if(i >= 2) ok1[s[i - 2] - 'a'][s[i - 1] - 'a'][s[i] - 'a'] = 0;
    	}
    }
    
    int main(){
    	int T;
    	std::cin >> T;
    	while(T--) solve();
    	return 0;
    } 
    

    C - Diluc and Kaeya

    好神的题。

    1. 首先这个比率一定是确定的值,每部分比率相同,所以应当每一段都等于全局的比率即 (frac{cnt_0}{cnt_1})
    2. 贪心能分就一定会分成两部分。

    故我们可以写出如下代码。

    复杂度 (O(n log n))(使用了 map)。

    code
    #include <bits/stdc++.h>
    
    #define debug(...) fprintf(stderr ,__VA_ARGS__)
    #define LL long long
    
    const int MX = 5e5 + 23;
    
    char s[MX];
    int cnt[MX];
    std::map<LL ,int> mp;
    
    int gcd(int a ,int b){return b ? gcd(b ,a % b) : a;}
    
    void solve(){
    	mp.clear();
    	int n; std::cin >> n;
    	scanf("%s" ,s + 1);
    	for(int i = 1 ; i <= n ; ++i){
    		cnt[i] = cnt[i - 1] + (s[i] == 'D');
    		int a = 0 ,b = 0;
    
    		
    		int c = gcd(cnt[i] ,i - cnt[i]);
    		a = cnt[i] / c ,b = (i - cnt[i]) / c;
    		
    		LL id = a * 1000000LL + b;
    		printf("%d%c" ,++mp[id] ," 
    "[i == n]);
    	}
    }
    
    int main(){
    	int T;
    	std::cin >> T;
    	while(T--) solve();
    	return 0;
    }
    

    D - Omkar and Medians

    记得有谁讲过这个套路。

    考虑每一回合的中位数的变化趋势,应该是要么不变,要么变成比它大/小的第一个数。

    故可以写出如下代码:

    时间复杂度 (O(n log n))

    code
    #include <bits/stdc++.h>
    
    #define debug(...) fprintf(stderr ,__VA_ARGS__)
    
    const int MX = 2e5 + 23;
    
    int a[MX];
    void solve(){
    	int n; std::cin >> n;
    	std::set<int> S;
    	int las = 0;
    	int ok = 1;
    	for(int i = 1 ,cur ; i <= n ; ++i){
    		std::cin >> cur;
    		if(i == 1) ;
    		else{
    			if(cur == las) continue;
    			if(cur > las){
    				auto k = S.upper_bound(las);
    				if(k == S.end() || cur <= *k){
    					;
    				}
    				else{
    					ok = 0;
    				}
    			}
    			if(cur < las){
    				auto k = S.lower_bound(las);
    				if(k == S.begin() || *std::prev(k) <= cur){
    					;
    				}
    				else ok = 0;
    			}
    		}
    		S.insert(cur);
    		las = cur;
    	}
    	puts(ok ? "YES" : "NO");
    }
    
    int main(){
    	int T;
    	std::cin >> T;
    	while(T--) solve();
    	return 0;
    }
    

    E - Omkar and Forest

    简单题,不懂为啥放这位置。

    不难发现,如果原图中存在一个非 0 位置,那么整张地图就是确定的。方案即 (2^w)(w)# 的数量。

    否则全图都是 #,此时答案是 (2^w-1)

    时间复杂度 (O(nm))

    code
    #include <bits/stdc++.h>
    
    #define debug(...) fprintf(stderr ,__VA_ARGS__)
    #define LL long long
    
    const int MX = 2000 + 3;
    const LL MOD = 1e9 + 7;
    
    LL qpow(LL a ,LL b ,LL p = MOD){
    	LL ans = 1;
    	while(b){if(b & 1) ans = ans * a % p;
    		a = a * a % p ,b >>= 1;
    	}return ans;
    }
    
    char str[MX][MX];
    void solve(){
    	int n ,m;
    	std::cin >> n >> m;
    	int possible = 0;
    	for(int i = 1 ; i <= n ; ++i){
    		scanf("%s" ,str[i] + 1);
    		for(int j = 1 ; j <= m ; ++j){
    			possible += str[i][j] == '#';
    		}
    	}
    	if(possible == n * m){
    		printf("%lld
    " ,qpow(2 ,possible) - 1);
    	}
    	else{
    		printf("%lld
    " ,qpow(2 ,possible));
    	}
    }
    
    int main(){
    	int T;
    	std::cin >> T;
    	while(T--) solve();
    	return 0;
    }
    

    F - Omkar and Akmar

    也是个简单题。

    打表/手玩/归纳法证明:不论怎么操作都是后手必胜,所以游戏等价于他们随便乱放的方案数。

    枚举最终的方案中的空格数量,假设确定了图中任意一个位置是填 A 还是 B,那么其余要填的 AB 就已经被确定了。

    现在就只要对放空格的方案计数了。加入要放 (i) 个则答案是 (inom{n-i}{i}+inom{n-i-1}{i-1})。为何?

    先不考虑环,我们把每一个空格都与前面的位置缩成一个,还原方案就是选择某些位置把它展开成两个,此部分方案数 (inom{n-i}{i})

    发现我们漏算的是开头的位置作为空位的方案数,我们按照同样的思路补算即可,此部分方案数 (inom{n-i-1}{i-1})

    然后我们还需要乘以 ((n-i)!)

    注意一点是,空位的奇偶性是确定的,不合法的方案不能算上

    时间复杂度 (O(n))

    code
    #include <bits/stdc++.h>
    
    #define debug(...) fprintf(stderr ,__VA_ARGS__)
    #define LL long long
    #define int long long
    
    const int MX = 1e6 + 23;
    const LL MOD = 1e9 + 7;
    
    int win[MX][2][2] ,fac[MX] ,inv[MX];
    void init(){
    	fac[0] = 1 ,inv[0] = inv[1] = 1;
    	for(int i = 1 ; i < MX ; ++i) fac[i] = 1LL * fac[i - 1] * i % MOD;
    	for(int i = 2 ; i < MX ; ++i) inv[i] = 1LL * (MOD - MOD / i) * inv[MOD % i] % MOD;
    	for(int i = 2 ; i < MX ; ++i) inv[i] = 1LL * inv[i] * inv[i - 1] % MOD;
    }LL C(int n ,int m){return 1LL * fac[n] * inv[m] % MOD * inv[n - m] % MOD;}
    
    LL calc(int n ,int k){
    	return (C(n - k ,k) + C(n - k - 1 ,k - 1)) % MOD;
    }
    
    signed main(){
    	init();
    	int n; std::cin >> n;
    	
    	int ans = 0;
    	if(n % 2 == 0){
    		ans = (ans + 2LL * fac[n]) % MOD;
    	}
    	for(int i = 1 + (n % 2 == 0) ; 2 * i <= n ; ++i){
    		LL way = calc(n ,i);
    		if((i & 1) == (n & 1)) ans = (ans + 2LL * fac[n - i] % MOD * way) % MOD;
    	}
    	printf("%lld
    " ,ans);
    	return 0;
    }
    

    总结

    简单场,

  • 相关阅读:
    linux 短信收发
    sama5d3 环境检测 adc测试
    【Codeforces 723C】Polycarp at the Radio 贪心
    【Codeforces 723B】Text Document Analysis 模拟
    【USACO 2.2】Preface Numbering (找规律)
    【Codeforces 722C】Destroying Array (数据结构、set)
    【USACO 2.1】Hamming Codes
    【USACO 2.1】Healthy Holsteins
    【USACO 2.1】Sorting A Three-Valued Sequence
    【USACO 2.1】Ordered Fractions
  • 原文地址:https://www.cnblogs.com/imakf/p/14868330.html
Copyright © 2011-2022 走看看