Codeforces #676 (div 2) 做题记录

A.

按二进制位从高到低贪心

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int T,a,b;
 4 int main()
 5 {
 6     scanf("%d",&T);
 7     while(T--)
 8     {
 9         scanf("%d%d",&a,&b);
10         int x=0;
11         for(int i=30;i>=0;--i)if((a&(1<<i))&&(b&(1<<i)))x|=(1<<i);
12         printf("%d\n",(a^x)+(b^x));
13     }
14 }
View Code

B.

左上角周围两个和右下角周围两个中翻转最多两个就行了

  1 #include<bits/stdc++.h>
  2 #define maxn 205
  3 using namespace std;
  4 int T,n;
  5 char s[maxn][maxn];
  6 int main()
  7 {
  8     scanf("%d",&T);
  9     while(T--)
 10     {
 11         scanf("%d",&n);
 12         for(int i=1;i<=n;++i)scanf("%s",s[i]+1);
 13         if(s[1][2]=='0'&&s[2][1]=='0')
 14         {
 15             if(s[n][n-1]=='1'&&s[n-1][n]=='1')
 16             {
 17                 printf("0\n");
 18             }
 19             else if(s[n][n-1]=='0'&&s[n-1][n]=='1')
 20             {
 21                 printf("1\n");
 22                 printf("%d %d\n",n,n-1);
 23             }
 24             else if(s[n][n-1]=='1'&&s[n-1][n]=='0')
 25             {
 26                 printf("1\n");
 27                 printf("%d %d\n",n-1,n);
 28             }
 29             else
 30             {
 31                 printf("2\n");
 32                 printf("%d %d\n",n,n-1);
 33                 printf("%d %d\n",n-1,n);
 34             }
 35         }
 36         else if(s[1][2]=='1'&&s[2][1]=='0')
 37         {
 38             if(s[n][n-1]=='1'&&s[n-1][n]=='1')
 39             {
 40                 printf("1\n");
 41                 printf("1 2\n");
 42             }
 43             else if(s[n][n-1]=='0'&&s[n-1][n]=='1')
 44             {
 45                 printf("2\n");
 46                 printf("%d %d\n",2,1);
 47                 printf("%d %d\n",n-1,n);
 48             }
 49             else if(s[n][n-1]=='1'&&s[n-1][n]=='0')
 50             {
 51                 printf("2\n");
 52                 printf("%d %d\n",2,1);
 53                 printf("%d %d\n",n,n-1);
 54             }
 55             else
 56             {
 57                 printf("1\n");
 58                 printf("%d %d\n",2,1);
 59             }
 60         }
 61         else if(s[1][2]=='0'&&s[2][1]=='1')
 62         {
 63             if(s[n][n-1]=='1'&&s[n-1][n]=='1')
 64             {
 65                 printf("1\n");
 66                 printf("2 1\n");
 67             }
 68             else if(s[n][n-1]=='0'&&s[n-1][n]=='1')
 69             {
 70                 printf("2\n");
 71                 printf("1 2\n");
 72                 printf("%d %d\n",n-1,n);
 73             }
 74             else if(s[n][n-1]=='1'&&s[n-1][n]=='0')
 75             {
 76                 printf("2\n");
 77                 printf("1 2\n");
 78                 printf("%d %d\n",n,n-1);
 79             }
 80             else
 81             {
 82                 printf("1\n");
 83                 printf("1 2\n");
 84             }
 85         }
 86         else
 87         {
 88             if(s[n][n-1]=='1'&&s[n-1][n]=='1')
 89             {
 90                 printf("2\n");
 91                 printf("%d %d\n",n,n-1);
 92                 printf("%d %d\n",n-1,n);
 93             }
 94             else if(s[n][n-1]=='0'&&s[n-1][n]=='1')
 95             {
 96                 printf("1\n");
 97                 printf("%d %d\n",n-1,n);
 98             }
 99             else if(s[n][n-1]=='1'&&s[n-1][n]=='0')
100             {
101                 printf("1\n");
102                 printf("%d %d\n",n,n-1);
103             }
104             else
105             {
106                 printf("0\n");
107             }
108         }
109     }
110 }
View Code

C.

考虑把第二个字符翻到前面形成回文串\(s_2 s_1 s_2\),然后整个复制翻到后面,那么就只差最后一个字符了,由前面的小回文串把倒数第二个翻过去就行了

 1 #include<bits/stdc++.h>
 2 #define maxn 100005
 3 using namespace std;
 4 char s[maxn];
 5 int n;
 6 int main()
 7 {
 8     scanf("%s",s+1);
 9     n=strlen(s+1);
10     puts("3");
11     printf("L %d\n",2);
12     printf("R %d\n",2);
13     printf("R %d\n",2*n-1);
14 }
View Code

D.

考虑做类似最短路的松弛操作,把每种向量的代价弄成最优的

然后就一定是两种走法拼到一起

 1 #include<bits/stdc++.h>
 2 #define ll long long 
 3 using namespace std;
 4 int T;
 5 ll x,y;
 6 ll c1,c2,c3,c4,c5,c6;
 7 ll a[8][8];
 8 int main()
 9 {
10     scanf("%d",&T);
11     while(T--)
12     {
13         scanf("%lld%lld",&x,&y);
14         scanf("%lld%lld%lld%lld%lld%lld",&c1,&c2,&c3,&c4,&c5,&c6);
15         while(1)
16         {
17             ll p2,p3,p5,p6;
18             p2=min(c2,c1+c3);
19             p3=min(c3,c2+c4);
20             p5=min(c5,c4+c6);
21             p6=min(c6,c1+c5);
22             if(c2==p2&&c3==p3&&c5==p5&&c6==p6)break;
23             c2=p2;c3=p3;c5=p5;c6=p6;
24         }
25         ll ans=0;
26         if(x>0)ans+=x*c6;else ans+=(-x)*c3;
27         if(y>0)ans+=y*c2;else ans+=(-y)*c5;
28         if(x>0)
29         {
30             ll res=0;
31             res+=x*c1;
32             if(y<x)res+=c5*(x-y);
33             else res+=c2*(y-x);
34             ans=min(ans,res);
35         }
36         else
37         {
38             ll res=0;
39             res+=(-x)*c4;
40             if(y<x)res+=c5*(x-y);
41             else res+=c2*(y-x);
42             ans=min(ans,res);
43         }
44         if(y>0)
45         {
46             ll res=0;
47             res+=y*c1;
48             if(x<y)res+=c3*(y-x);
49             else res+=c6*(x-y);
50             ans=min(ans,res);
51         }
52         else
53         {
54             ll res=0;
55             res+=(-y)*c4;
56             if(x<y)res+=c3*(y-x);
57             else res+=c6*(x-y);
58             ans=min(ans,res);
59         }
60         printf("%lld\n",ans);
61     }
62 }
View Code

E.

考虑最后的合并是一个二叉树结构,在二叉树的奇数层(根深度为1)的叶子贡献为-1,偶数层贡献为+1

那么我们假设第\(k\)层叶子的权值为\(\frac{1}{2^k}\),那么总权值是\(1\)

在mod 3意义下,奇数层权值是\(2\),偶数层权值是\(1\)

这等价于前面的贡献

我们将叶子从左到右的权值做前缀和,在mod 3意义下一定是从\(0\)开始到\(1\)结束

只要这棵二叉树能构造出来,这种方案就一定合法

二叉树能构造出来等价于一定有一个位置为\(2\),这个可以用归纳证明

然后\(dp[i][0/1/2][0/1]\)表示dp到第\(i\)位,前缀和mod 3为多少,然后有没有经过\(2\)的最大值

 1 #include<bits/stdc++.h>
 2 #define maxn 200005
 3 #define ll long long
 4 using namespace std;
 5 int n;
 6 ll a[maxn];
 7 ll dp[maxn][3][2];
 8 const ll inf = (ll)1e18;
 9 int main()
10 {
11     scanf("%d",&n);
12     for(int i=1;i<=n;++i)scanf("%lld",&a[i]);
13     if(n==1)
14     {
15         printf("%lld\n",a[1]);
16         return 0;
17     }
18     for(int i=0;i<=n;++i)
19         for(int j=0;j<3;++j)
20             for(int k=0;k<2;++k)dp[i][j][k]=-inf;
21     dp[0][0][0]=0;
22     for(int i=0;i<n;++i)
23         for(int j=0;j<3;++j)
24             for(int k=0;k<2;++k)
25             {
26                 int p;
27                 p=k;
28                 if((j+1)%3==2)p=1;
29                 dp[i+1][(j+1)%3][p]=max(dp[i+1][(j+1)%3][p],dp[i][j][k]+a[i+1]);
30                 p=k;
31                 if((j+2)%3==2)p=1;
32                 dp[i+1][(j+2)%3][p]=max(dp[i+1][(j+2)%3][p],dp[i][j][k]-a[i+1]);
33             }
34     cout<<dp[n][1][1]<<endl;
35 }
View Code

 

posted @ 2020-10-19 20:04  幽蝶  阅读(188)  评论(0编辑  收藏  举报