码迷,mamicode.com
首页 > 其他好文 > 详细

2020.03.09 Educational Codeforces Round 83 (Rated for Div. 2)

时间:2020-03-10 11:44:13      阅读:87      评论:0      收藏:0      [点我收藏+]

标签:文件   求逆   情况   str   flag   fir   margin   表示   vector   

题目文件下载 

比赛链接

ps: 这是我第一次打CF = = div2的7题只做对了3题,还是太弱了,以后要变强!

 另外,我的证明有些比较多余,不想看可以跳过~~

 欢迎指出错误~

 

A. Two Regular Polygons
 
大意: 给定两个数n,m,问是否可以找到一组正n边型和正m边型,使得正m边型的m个顶点恰好都是正n边型的顶点,且正m边型的几何中心与正n边型的几何中心重合。 注意,每一个多边形都是凸面多边形,即每一个内角都小于 PI
解答: 只要n可以整除m即可。
可以用数学方法证明如下:技术图片
代码(还需要写吗....)
 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     后面三题等我做了再发 ---

E. Array Shrinking

 

技术图片

2020.03.09 Educational Codeforces Round 83 (Rated for Div. 2)

标签:文件   求逆   情况   str   flag   fir   margin   表示   vector   

原文地址:https://www.cnblogs.com/popodynasty/p/12453685.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!