zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 84 (Rated for Div. 2) A-E题解

    A. Sum of Odd Integers

    首先可以算出从1开始到第k个奇数之和。如果和大于n,则不可能存在k个奇数加和等于n,否则用n减去前k个奇数的和,这个差值若是偶数,直接加到最大的奇数上,就可以满足题意要求,否则输出no。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 int main(){
     5     int t;
     6     cin>>t;
     7     while(t--){
     8         ll n,k;
     9         cin>>n>>k;
    10         ll d = (1+2*k-1)*k/2;
    11         ll t = n - d;
    12         if(t>=0 && t%2 == 0) cout<<"YES"<<endl;
    13         else cout<<"NO"<<endl;
    14     }
    15     return 0;
    16 }
    View Code

    B. Princesses and Princes

    贪心的去匹配每个Princesses当前可以匹配的最中意的Princes,如果存在没有匹配上的Princesses,随便和一个没有匹配过的Princes匹配即可。纯阅读理解题。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 int main(){
     5     int t;
     6     cin>>t;
     7     while(t--){
     8         int n;cin>>n;
     9         vector<int> v[n];
    10         int pr[n+1];
    11         int dr[n+1];
    12         memset(dr,0,sizeof(dr));
    13         memset(pr,0,sizeof(pr));
    14         for(int i = 1;i<=n;i++){
    15             int k;scanf("%d",&k);
    16             for(int j = 0;j<k;j++){
    17                 int t;scanf("%d",&t);
    18                 if(dr[i] == 0 && pr[t] == 0) pr[t] = 1,dr[i] = 1;
    19             }
    20         }
    21         vector<int> r1,r2;
    22         int f = 0;
    23         for(int i = 1;i<=n;i++){
    24             if(dr[i] == 0) {
    25                 f = 1;r1.push_back(i);
    26             }
    27             if(pr[i] == 0) {
    28                 f = 1;r2.push_back(i);
    29             }
    30         }
    31         if(f == 0){
    32             cout<<"OPTIMAL"<<endl;
    33         }
    34         else{
    35             cout<<"IMPROVE"<<endl;
    36             for(int i = 0;i<r1.size();i++){
    37                 cout<<r1[i]<<" "<<r2[i]<<endl; 
    38                 break;
    39             }
    40         }
    41     }
    42     return 0;
    43 }
    View Code

    C. Game with Chips

    构造题。按最坏的情况考虑,直接先把所有的chips移动到一个角落里,然后从这个角落S形遍历一遍棋盘即可,这样必定可以经过棋盘上所有的关键点,整个操作必定不会超过2*m*n次,故不可能存在-1的情况。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 int main()
     5 {
     6  
     7     int n,m,k;
     8     cin>>n>>m>>k;
     9     for(int i=1;i<=k;i++)
    10     {
    11         int x,y;scanf("%d%d",&x,&y);
    12     }
    13     for(int i=1;i<=k;i++)
    14     {
    15        int x,y;scanf("%d%d",&x,&y);
    16     }
    17     int tn=0;
    18         tn =tn+n-1+m-1+(n-1)*m+m-1;
    19     cout << tn << endl;
    20     for(int i=1; i<m; i++ )
    21         cout<<"L";
    22     for(int i=1; i<n; i++)
    23         cout<<"U";
    24             for(int i=1; i<n; i++)
    25                 {
    26                     for(int j=1; j<m; j++)
    27                     if(i&1)
    28                         cout<<"R";
    29                     else
    30                         cout<<"L";
    31                             printf("D");
    32                 }
    33     for(int j=1; j<m; j++)
    34         if (n&1)
    35             printf("R");
    36         else
    37             printf("L");
    38 
    39     return 0;
    40 }
    View Code

    D. Infinite Path

    一道定义在环上的排列幂定义题。p * p = p[ p [ i ] ] ,按照题目所给的定理可以轻易推导出从任意一p[i]出发,做排列幂运算之后最终回到p[i],把i和p[i]连边,这样可以构成一个环,而整个序列可以构成多个不相交环。对于一个环,从任意一点出发,走k步,也就是pk[i] ,会有c[i] = c[pk[i] ] ,也可能会有c[p2k[i] ]......,也就是说每次走从一点开始,相隔k个点,他们的c[i]是相等的,怎么求最小的k?当是从环长度的因子开始枚举,只有是因子k才能从某一起点开始,每次走k步,绕一圈回到这个起点。

    预处理所有的环,然后枚举环,在环中枚举环长度的因子,再去检查环上是否存在合法的k,每次取k的最小值。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int maxn = 2e5 +5;
     5 int k,n,cnt,ans;
     6 int p[maxn],c[maxn],vis[maxn],g[maxn];
     7 bool ok(int x,int y){
     8     for(int i = 1;i<=x;i++){//在长度为x的范围内枚举起点
     9         int f = 0,t = i;
    10         for(int j = 1;j<=y;j++){//整个环上有y个相隔x的点
    11             if(c[g[t]] != c[g[i]]){//检查每次移动k步到的点,其c值是否相等。
    12                 f = 1;break;
    13             }
    14             t = (t + x - 1) %cnt + 1;//t是下一个点的位置
    15         }
    16         if(!f) return 1;
    17     }
    18     return 0;
    19 }
    20 void dfs(int x){
    21     cnt = 1;
    22     g[cnt] = x,vis[x] = 1;
    23     for(int i = p[x];i!=x;i=p[i]) vis[i] = 1,g[++cnt] = i;//从一点开始预处理环,结点存入g数组
    24     for(int i = 1;i<=sqrt(cnt);i++){//枚举环长度cnt的因子
    25         if(cnt%i == 0){
    26             if(ok(i,cnt/i)) {ans = min(ans,i);return;} //检查k = i是否合法
    27             if(ok(cnt/i,i) )ans = min(ans,cnt/i);//检查k = cnt/i是否合法
    28         }
    29     }
    30 }
    31 int main()
    32 {
    33     int t;
    34     scanf("%d",&t);
    35     while(t--){
    36        scanf("%d",&n);
    37        for(int i = 1;i<=n;i++) scanf("%d",&p[i]);
    38        for(int i = 1;i<=n;i++) scanf("%d",&c[i]);
    39        ans = 2e5+10;
    40        for(int i = 1;i<=n;i++) vis[i] = 0; 
    41        for(int i = 1;i<=n;i++) {
    42               if(!vis[i]) dfs(i);
    43        }
    44        cout<<ans<<endl;
    45     }
    46     return 0;
    47 }
    View Code

    E. Count The Blocks

    计数题。n位数,首先考虑block的长度为1,各个位置都可以放置0~10这样不同的数字,一共10个数字,对于其中1个位置,这个位置可以放10种可能的数字,其左右相邻的位放置9种可能的数,不相邻的其他位可以任意放置10个数字。

    考虑长度n的数,block长度为k

    1.左右两个端点对答案的贡献是2*10*9*10n-k-1 ,2是2个端点,10是端点可以放置10种可能的数,9是其相邻位置只能放9种可能,10n-k-1是其他点可以放置的数字有多少种。

    2.中间的长度为k的段,10*9*9*10n-k-2,10是这一段放置10种可能的数字,2个9是这一段左右端点相邻的点要和段内数字不同,有9种可能,10n-k-2 是其他点可以放置的数字有多少种可能,这样的段一共有n-k-1个,再乘一下即可。

    首先要预处理一下10的n次方。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const ll mod = 998244353;
     5 const int maxn = 2e5+5;
     6 ll n;
     7 ll f[maxn];
     8 void pre(){
     9     f[1] = 10;
    10     for(int i = 2;i<=n;i++){
    11        f[i] = f[i-1]*10%mod;        
    12     }
    13 }
    14 int main()
    15 {
    16     cin>>n;
    17     pre();
    18     for(int i = 1;i<n;i++){
    19         ll d = n + 1 - i;
    20         ll x = ((ll(2*9)*f[n-i])%mod + (ll(d-2)*9*9*f[n-i-1])%mod)%mod;
    21         cout<<x<<" ";
    22     }
    23     cout<<10;
    24     return 0;
    25 }
    View Code
  • 相关阅读:
    centos6安装创建kvm虚拟机
    centos6安装创建kvm虚拟机
    centos6安装创建kvm虚拟机
    centos6安装创建kvm虚拟机
    18岁主动申请退学,22岁就成了百万富翁,他怎样创业的?
    多次创业转向餐饮业,他开了10家小店,生意红火
    为挽救濒临破产企业,他提出的方案竟然“一炮而红”
    靠开焊接厂赚了很多钱,他的成功很经典,值得参考
    一道传统特色小吃让她萌生创业想法,一天能挣800元
    蛋糕做出新高度,投资不高却收入“甜蜜”,他们怎样做的?
  • 原文地址:https://www.cnblogs.com/AaronChang/p/12571826.html
Copyright © 2011-2022 走看看