codeforces-1332D-Walk on Matrix

codeforces-1332D-Walk on Matrix

传送门:https://codeforces.com/problemset/problem/1332/D

题意:有一个矩阵,每次可以向下或向右移动,把路径上的所有数都&起来,如果还是dp显然是错的。假设dp的到的结果是x,正确答案是y。

现在给定k,需要你构造一个矩阵,使得|y-x|=k

因为dp是错的,你就要找到他是哪里错了

我们可以看给出的样例

3 4
7 3 3 1
4 8 3 6
7 7 7 3
In the second example, the maximum score Bob can achieve is 7&3&3&3&7&3=3, while the output of his algorithm is 2.

模拟一下这个过程,我们把他转换为更为清晰的二进制


如图,橙色为dp路线,而根据样例给出的解释,红色才是正解,很明显,路线从第三行第三列开始偏了,那么我们就从这开始入手


他是怎么出错的呢?dp[3][3] 0111在面对0100和0011时选择了能让他与结果更大的0100,而他也变成了0100,在与0011进行与运算时答案变成了0


但如果是最优情况,他会与0011进行与运算变成0011,在与他的右面进行与运算变成0011=3


利用这个bug,我们就可以解题了,因为是要|y-x|=k,我们可以构造出dp情况=0,而正解为k的一个矩阵(准确的来讲,是这么一个拐角)

模拟上面的拐角,我们把拐角放到左下角,我们构造出的,长这样:

但是你模拟一下,发现不对,标橙的那个k跟上或左进行与运算后变成了0,然鹅我们要保证这个位置运算之后是k,而且那个111111不能变

别忘了11111111和任何数与运算都是它本身,所以蓝色部分应该变成1111111……

橙色两个数的位置也并不影响答案,换一下就行,11111……的10000……从上面传过来,k正好从左面传过来

它就变成了这样子

因为是自己决定矩阵的大小,我们发现,有用的只有灰色部分,那就只输出这部分就好了

还有就是位运算的优先级很低,能加括号的把括号都加上,还有规定a[i][j]最大是3e5,不能再往大了开了(wa了几发呢)

细节细节

上代码

 1 #include<stdio.h>
 2 #include<string.h>
 3 using namespace std;
 4 #define ll long long
 5 int dp[5][5];
 6 int main()
 7 {
 8     memset(dp,0,sizeof(dp));
 9     int k;
10     scanf("%d",&k);
11     dp[1][1]=dp[2][2]=(1<<18)-1;
12     dp[1][2]=1<<17;
13     dp[2][1]=dp[2][3]=k;
14     puts("2 3");
15     for(int i=1;i<=2;i++)
16     {
17         for(int j=1;j<=3;j++) printf("%d ",dp[i][j]);
18         printf("
");
19     }
20     return 0;
21 }


 
原文地址:https://www.cnblogs.com/YangKun-/p/12636016.html