2020.03.09 Educational Codeforces Round 83 (Rated for Div. 2)
Posted popodynasty
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2020.03.09 Educational Codeforces Round 83 (Rated for Div. 2)相关的知识,希望对你有一定的参考价值。
ps: 这是我第一次打CF = = div2的7题只做对了3题,还是太弱了,以后要变强!
另外,我的证明有些比较多余,不想看可以跳过~~
欢迎指出错误~
1 #include <iostream> 2 using namespace std; 3 int main(){ 4 int t; 5 cin >> t; 6 while (t--) { 7 int n,m; 8 cin >> n >> m; 9 if(n%m) 10 cout<<"NO"<<endl; 11 else 12 cout<<"YES"<<endl; 13 } 14 return 0; 15 }
B. Bogosort
将表达式移项可以得到 ai - aj != i - j 即可,由于 i - j < 0 ,我们可以让 ai >= aj ,故将数组非递增排序。
1 #include <iostream> 2 #include <algorithm> 3 #include <vector> 4 using namespace std; 5 int main(){ 6 int t; 7 cin >> t; 8 while (t--) { 9 int n,temp; 10 vector<int> vec; 11 cin >> n; 12 for(int i = 0; i < n; i++){ 13 cin >> temp; 14 vec.push_back(temp); 15 } 16 sort(vec.begin(),vec.end()); 17 int first = 1; 18 for(int i = n-1; i >= 0; i--){ 19 if(first) 20 first = 0; 21 else 22 cout<<‘ ‘; 23 cout<<vec[i]; 24 } 25 cout<<endl; 26 } 27 return 0; 28 }
C. Adding Powers
对于给定一个数x,如果x可以展开成底数k的幂的和的形式,那么 x % k = 1 或 x % k = 0
由于题目中要求每一步只能增加 k ^ step,故每一种k的幂次只能使用一次。因此,如果想得到目标数列,当且仅当每一个数都可以展开为底数k的幂的和的形式,且不重复食用任何一种k的幂(即k的指数各不相同)。
如何将数x分解为k的幂的形式呢?方法是每次求出一个指数idx,使得pow(k,idx)是最大的不超过x的幂。
我们可以利用等比数列求和的公式证明,如果将数x展开成k的幂,同时又没有使用最大的k的幂,那么一定会出现某一个k的幂被重复利用的情况。( 不妨验证 Sn-1 < An ,其中 An = k ^ (n-1) , n = 1,2,3..... )
因此用一个vis数组记录当前的指数是否用过了,如果用过了,返回false,表示失败。
1 #include <iostream> 2 #define Maxsize 30+1 3 using namespace std; 4 typedef long long ll; 5 ll dest[Maxsize]; 6 bool vis[100]; 7 ll quick_pow(ll base,int idx){ 8 ll ans = 1; 9 while (idx) { 10 if(idx&1) 11 ans *= base; 12 base *= base; 13 idx >>= 1; 14 } 15 return ans; 16 } 17 bool solve(ll dest,ll base){ 18 if(dest == 0) 19 return true; 20 int max_step = -1; 21 while (quick_pow(base,max_step+1) <= dest) { 22 max_step++; 23 } 24 if(vis[max_step]) 25 return false; 26 vis[max_step] = true; 27 return solve(dest-quick_pow(base,max_step),base); 28 } 29 int main(){ 30 int t; 31 cin >> t; 32 while (t--) { 33 fill(vis,vis+100,false); 34 int flag = 1; 35 int n,base; 36 cin >> n >> base; 37 for(int i = 1; i <= n; i++){ 38 cin >> dest[i]; 39 } 40 for(int i = 1; i <= n; i++){ 41 if(! solve(dest[i],base)){ 42 flag = 0; 43 break; 44 } 45 } 46 if(flag) 47 cout<<"YES"<<endl; 48 else 49 cout<<"NO"<<endl; 50 } 51 return 0; 52 }
D. Count the Arrays
一开始只想到了C(n-1,m) * (n-2) , 没想到最后的 * 2^(n-3)。难怪比赛的时候一直交不对......
注意还有n=2的特判。
这里贴一个解释的比较清楚的评论~
这题主要涉及组合数学。 需要会使用 ‘快速幂取模’ , ‘费马小定理求逆元’ 。
还有就是貌似用递归求处理阶乘取模会爆?我后来改成了循环dp求阶乘。这个不难,注意一下就好。
1 #pragma GCC optimize("Ofast") 2 #include <iostream> 3 #define MOD 998244353 4 #define Maxsize 200000+1 5 using namespace std; 6 typedef long long ll; 7 ll fact[Maxsize]; 8 ll quick_pow(ll base,ll idx){ 9 ll ans = 1; 10 while (idx) { 11 if(idx&1){ 12 ans *= base; 13 ans %= MOD; 14 } 15 base *= base; 16 base %= MOD; 17 idx >>= 1; 18 } 19 return ans; 20 } 21 ll inv(ll a,ll p){ // 费马小定理 inv(a) = a^(p-2) (a*inv(a) = 1(mod p )) 22 return quick_pow(a,p-2); 23 } 24 ll C(int up,int down){ 25 if(up > down)return 0; 26 else if(up == down)return 1; 27 else return fact[down] * inv(fact[up],MOD) % MOD * inv(fact[down-up],MOD) % MOD; 28 } 29 int main(){ 30 int n,m; 31 cin >> n >> m; 32 fact[0] = 1; 33 for(int i = 1; i <= m; i++){ 34 fact[i] = i * fact[i-1] % MOD; 35 } 36 if(n > 2){ // 特判,测试点6会出现 n = 2的情况 37 ll ans = (C(n-1,m) * (n-2)%MOD * quick_pow(2,n-3) % MOD + MOD) % MOD; 38 cout<<ans; 39 }else{ 40 cout<<0; 41 } 42 return 0; 43 }
--- 先写这么多 0 . 0 后面三题等我做了再发 ---
以上是关于2020.03.09 Educational Codeforces Round 83 (Rated for Div. 2)的主要内容,如果未能解决你的问题,请参考以下文章
2020.03.09 Educational Codeforces Round 83 (Rated for Div. 2)