• 【题解】 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;
    }
    

    总结

    简单场,

  • 相关阅读:
    【Java123】enum枚举及其应用
    sql查询优化_慢查询
    9.4 如何实现属性可修改的函数装饰器?
    9.2 如何为被装饰的函数保存元数据?
    python的如何通过实例方法名字的字符串调用方法?
    9.1 如何使用函数装饰器 用装饰器解决重复计算问题
    asyncio 笔记
    python笔记截图
    list绑定
    表单数据交互
  • 原文地址:https://www.cnblogs.com/imakf/p/14868330.html
Copyright © 2020-2023  润新知