CF809C(找规律+数位DP)

老年选手需要多写一些思维题qwq。

通过打表很容易发现对于(i,j),值为(i-1)^(j-1)+1,然后本题就没了qwq

矩阵差分还是很容易想到的,容斥成四个矩阵。

然后看到异或很容易想到三件事:数位DP、字典树、线性基。很容易发现后两种与本题不符,就是数位DP了,从高位到低位DP,f[i][0/1][0/1][0/1]表示到第i位,当前的x、y、x^y是否达到上界,然后直接暴力枚举当前位即可。因为q<=1e4怕memset多了出事,我用了滚动数组qwq。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+10,mod=1e9+7;
int f[2][2][2][2],g[2][2][2][2];
void add(int&x,int y){x=x+y>=mod?x+y-mod:x+y;}
ll work(int n,int m,int k)
{
    if(n<0||m<0)return 0;
    memset(f,0,sizeof f),memset(g,0,sizeof g);
    int p=1;
    g[0][1][1][1]=1;
    for(int i=30;~i;i--)
    {
        int x=n>>i&1,y=m>>i&1,z=k>>i&1;
        for(int j=0;j<=1;j++)
        for(int k=0;k<=1;k++)
        for(int l=0;l<=1;l++)
        if(g[p^1][j][k][l])
        {
            for(int X=0;X<=(x|(!j));X++)
            for(int Y=0;Y<=(y|(!k));Y++)
            if((X^Y)<=z||!l)
            {
                add(f[p][j&(X==x)][k&(Y==y)][l&((X^Y)==z)],(f[p^1][j][k][l]+1ll*g[p^1][j][k][l]*((X^Y)<<i)%mod)%mod);
                add(g[p][j&(X==x)][k&(Y==y)][l&((X^Y)==z)],g[p^1][j][k][l]);
            }
            f[p^1][j][k][l]=g[p^1][j][k][l]=0;
        }
        p^=1;
    }
    int ans=0;
    for(int j=0;j<=1;j++)
    for(int k=0;k<=1;k++)
    for(int l=0;l<=1;l++)
    add(ans,(f[p^1][j][k][l]+g[p^1][j][k][l])%mod);
    return ans;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int ax,ay,bx,by,k;scanf("%d%d%d%d%d",&ax,&ay,&bx,&by,&k);
        ax--,ay--,bx--,by--,k--;
        printf("%lld\n",((work(bx,by,k)-work(ax-1,by,k)-work(bx,ay-1,k)+work(ax-1,ay-1,k))%mod+mod)%mod);
    }
}
View Code

 

posted @ 2019-06-04 20:03  hfctf0210  阅读(424)  评论(3编辑  收藏  举报