zoukankan      html  css  js  c++  java
  • Codeforces Round #553 (Div. 2)

    传送门


    A. Maxim and Biology

      题意:

        给出一个串s,问最少需要多少步操作使得串s包含"ACTG"这个子串,输出最少操作次数;

      题解:

        枚举每个位置 i,求出将 i,i+1,i+2,i+3 变为 "ACTG" 所需的最少操作次数即可;

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define INF 0x3f3f3f3f
     4 #define ll long long
     5 #define mem(a,b) memset(a,b,sizeof(a))
     6 
     7 int n;
     8 char s[100];
     9 
    10 int Step(char x1,char x2)//求解x1变为x2所需的最少操作步骤
    11 {
    12     if(x1 <= x2)
    13         return min(x2-x1,x1-'A'+'Z'-x2+1);
    14     else
    15         return min(x1-x2,'Z'-x1+x2-'A'+1);
    16 }
    17 //求解以index位置开始使得其连续的四个字符变为"ACTG"所需的最小操作步骤
    18 int F(int index)
    19 {
    20     int ans=0;
    21     ans += Step(s[index],'A');
    22     ans += Step(s[index+1],'C');
    23     ans += Step(s[index+2],'T');
    24     ans += Step(s[index+3],'G');
    25     return ans;
    26 }
    27 int Solve()
    28 {
    29     int ans=INF;
    30     int len=strlen(s);
    31     for(int i=0;i+4 <= len;++i)
    32         ans=min(ans,F(i));
    33     return ans;
    34 }
    35 int main()
    36 {
    37 //    freopen("C:\Users\hyacinthLJP\Desktop\in&&out\contest","r",stdin);
    38     while(~scanf("%d",&n))
    39     {
    40         scanf("%s",s);
    41         printf("%d
    ",Solve());
    42     }
    43     return 0;
    44 }
    View Code

    B. Dima and a Bad XOR

      题意:

        给出一个 n*m 的矩阵a[][],每一行任选一个元素,判断选出的这 n 个元素的异或和是否大于0;

        如果存在大于0的选法,输出 "TAK" ,并且输出每一行选择的元素的列标;

        如果不存在,输出 "NIE";

      题解:

        令 ans = a[1][1]^a[2][1]^........^a[n][1];

        ①ans > 0 : 输出 n 个 1

        ②ans == 0 : 判断是否可以将a[1][1] 或 a[2][1] 或 ..... 或 a[n][1] 变成同一行的其他元素;

                如果可以,输出 "TAK",并将任意一个a[ i ][1]变为同行中的其他元素;

              反之,输出"NIE";

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 int n,m;
     5 int a[600][600];
     6 int tmp[600];
     7 
     8 bool isSat()//判断是否存在去重后的元素个数 > 1 的行
     9 {
    10     for(int i=1;i <= n;++i)
    11     {
    12         /**
    13             如果想要从tmp[1]位置作为起始位置,第一个参数为tmp+1
    14             a[i]数组第一个位置的下标为a[i][1],所以第二个参数为a[i]+1
    15             第三个参数不是指数组个数,而是指要复制的数据的总字节数长度
    16         */
    17         memcpy(tmp+1,a[i]+1,m*sizeof(int));//将a[i]数组拷贝给tmp数组
    18         sort(tmp+1,tmp+m+1);
    19         int t=unique(tmp+1,tmp+m+1)-tmp;//去重
    20         t--;
    21         if(t > 1)
    22             return true;
    23     }
    24     return false;
    25 }
    26 void Solve()
    27 {
    28     int ans=0;
    29     for(int i=1;i <= n;++i)
    30         ans ^= a[i][1];
    31 
    32     if(ans != 0 || ans == 0 && isSat())
    33     {
    34         printf("TAK
    ");
    35         bool flag=(ans != 0);//如果ans != 0,输出n个1
    36         for(int i=1;i <= n;++i)
    37         {
    38             if(!flag)
    39             {
    40                 for(int j=2;j <= m;++j)
    41                     if(a[i][j] != a[i][1])
    42                     {
    43                         flag=true;//如果ans=0,找到第一个相异与a[i][1]的元素的列标即可
    44                         printf("%d ",j);
    45                         break;//记得break,不然,printf("%d ",j) 可能会调用多次
    46                     }
    47                 if(!flag)
    48                     printf("1 ");
    49             }
    50             else
    51                 printf("1 ");
    52         }
    53         printf("
    ");
    54     }
    55     else
    56         printf("NIE
    ");
    57 }
    58 int main()
    59 {
    60     while(~scanf("%d%d",&n,&m))
    61     {
    62         for(int i=1;i <= n;++i)
    63             for(int j=1;j <= m;++j)
    64                 scanf("%d",a[i]+j);
    65         Solve();
    66     }
    67     return 0;
    68 }
    View Code

     


    C. Problem for Nazar

      题意:

        给定奇数集和偶数集;

        现构造一个数组:

        先取奇数集中 20 个元素1,再取偶数集中 21 个元素2,4;

        再取奇数集中 22素 {3,5,7,9},再取偶数集中 23 个元素 {6,8,10……};

        ............

        得到  {1,2,4,3,5,7,9,6,8,10,12……} ;

        问这个数组的某一区间 [l,r] 的区间和是多少,并对1e9+7取模。

      思路一:

        分别求出区间[l,r]对应的 {oddS,oddE},{evenS,evenE}

        oddS:区间[l,r]的第一个奇数

        oddE:区间[l,r]的最后一个奇数

        evenS,evenE同理;

        

        (oddSum:{oddS,....,oddE}之间的奇数个数,evenSum同理)

        最后输出ans%mod即可;

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 const int mod=1e9+7;
     5 
     6 ll l,r;
     7 
     8 ll fOdd(int x)///找2^x个连续的奇数开始的奇数
     9 {
    10     ll tot=((1ll*1<<x)-1)/3;
    11     return 1+(tot<<1);
    12 }
    13 ll fEven(int x)///找2^x个连续的偶数开始的偶数
    14 {
    15     ll tot=((1ll*1<<x)-2)/3;
    16     return 2+(tot<<1);
    17 }
    18 ll quickPower(ll _a,ll _b,ll _mod)
    19 {
    20     ll ans=1;
    21     while(_b)
    22     {
    23         if(_b&1)
    24             ans=ans*_a%mod;
    25         _a=(_a*_a)%mod;
    26         _b >>= 1;
    27     }
    28     return ans;
    29 }
    30 ll Solve()
    31 {
    32     int x,y;
    33     for(x=0;(1ll*1<<(x+1))-1 < l;++x);///包含l的最大的x
    34     for(y=0;(1ll*1<<(y+1))-1 < r;++y);///包含r的最大的y
    35 
    36     ll oddS=!(x&1)/**判断x是否为偶数*/ ? fOdd(x)+(l-(1ll*1<<x))*2:fOdd(x+1);
    37     ll evenS=(x&1)/**判断x是否为奇数*/ ? fEven(x)+(l-(1ll*1<<x))*2:fEven(x+1);
    38 
    39     ll oddE=!(y&1) ? fOdd(y)+(r-(1ll*1<<y))*2:fOdd(y+1)-2;
    40     ll evenE=(y&1) ? fEven(y)+(r-(1ll*1<<y))*2:fEven(y+1)-2;
    41 
    42     ll ans=0;
    43     if(oddE >= oddS)
    44     {
    45         ll n=((oddE-oddS)>>1)+1;
    46         ll d=oddE+oddS;
    47         ///被除数2可以将其约掉(d肯定为偶数)
    48         ///也可以用逆元进行除法取模
    49         ///我用的是逆元除法取模(有点麻烦)
    50         ans += ((n%mod)*(d%mod)%mod)*(quickPower(2,mod-2,mod))%mod;
    51     }
    52     if(evenE >= evenS)
    53     {
    54         ll n=((evenE-evenS)>>1)+1;
    55         ll d=evenE+evenS;
    56         ans += ((n%mod)*(d%mod)%mod)*(quickPower(2,mod-2,mod))%mod;
    57     }
    58     return ans%mod;
    59 }
    60 int main()
    61 {
    62 //    freopen("C:\Users\hyacinthLJP\Desktop\in&&out\contest","r",stdin);
    63     scanf("%lld%lld",&l,&r);
    64     printf("%lld
    ",Solve());
    65     return 0;
    66 }
    View Code

     思路二:

        前 i 个偶数的和为 i*(i+1)

        前 i 个奇数的和为 i*i

        求解出前 r 个奇数,偶数个数,求出答案

        求解出前 l-1 个奇数,偶数个数,求出答案,两者做差便是最终答案

    AC代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 const int mod=1e9+7;
     5 
     6 ll l,r;
     7 
     8 ll Solve(ll x)///分别求解出[1,x]中奇数个数,偶数个数
     9 {
    10     ll oddSum=0;
    11     ll evenSum=0;
    12     for(int i=0;;i++)
    13     {
    14         if((1ll*1<<(i+1))-1 >= x)///包含x的最大的2^i
    15         {
    16             if(i&1)
    17                 evenSum += (x-(1ll*1<<i)+1)%mod;
    18             else
    19                 oddSum += (x-(1ll*1<<i)+1)%mod;
    20             break;
    21         }
    22         if(i&1)
    23             evenSum += (1ll*1<<i)%mod;
    24         else
    25             oddSum += (1ll*1<<i)%mod;
    26         evenSum %= mod;
    27         oddSum %= mod;
    28     }
    29     ///[1,x]的区间和
    30     return (evenSum%mod*(evenSum+1)%mod%mod+oddSum%mod*(oddSum%mod)%mod)%mod;
    31 }
    32 int main()
    33 {
    34 //    freopen("C:\Users\hyacinthLJP\Desktop\in&&out\contest","r",stdin);
    35     scanf("%lld%lld",&l,&r);
    36 
    37     ///注意,取模做减法有可能变成负值,需要再加个mod,再模一次mod
    38     printf("%lld
    ",(Solve(r)-Solve(l-1)+mod)%mod);
    39 
    40     return 0;
    41 }
    View Code
  • 相关阅读:
    MATLAB入门学习(一)
    4.21小练
    poj2312 Battle City 【暴力 或 优先队列+BFS 或 BFS】
    Mutual Training for Wannafly Union #2
    4.7-4.9补题+水题+高维前缀和
    CodeForces 91A Newspaper Headline
    codeforces 792C. Divide by Three
    3.26-3.31【cf补题+其他】
    poj3259 Wormholes【Bellman-Ford或 SPFA判断是否有负环 】
    二叉树基础练习
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/10733951.html
Copyright © 2011-2022 走看看