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\n",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\n");
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("\n");
54     }
55     else
56         printf("NIE\n");
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\n",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\n",(Solve(r)-Solve(l-1)+mod)%mod);
39 
40     return 0;
41 }
View Code

 

posted @ 2019-04-19 09:22  HHHyacinth  阅读(145)  评论(0编辑  收藏  举报