【bsgs】hdu4887

来源:互联网 发布:python课程推荐 编辑:程序博客网 时间:2024/06/09 14:37

可以看出这些操作是可以用一些异或实现,而异或又是满足结合律的,因此可以写成矩阵的形式

那么题目的实质就是求A^K*X=Y

就是经典的离散对数

可以写成A^(K1*SQRT(N)-K2)*X=Y -> A^(K1*sqrt(n))*X=A^K2*Y

左右两边都是sqrt(n)级别的问题,左边枚举,右边用个hash存一下答案

在算右边的答案的时候可以直接用位运算,左边的初始矩阵可以用快速幂求。

#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#include <map>#include <cmath>using namespace std;struct matrix{    int p[33][33];    int n,m;    matrix () {}    matrix (int N,int M) {        n=N,m=M;        memset(p,0,sizeof(p));    }    matrix (unsigned int t,int N,int M)    {        n=N,m=M;        memset(p,0,sizeof(p));        for (int i=n;i>=2;i--,t>>=1)            p[i][1]=(t&1);        p[1][1]=1;    }    matrix operator *(matrix &a) {        matrix tmp(n,a.m);        for (int i=1;i<=n;i++)            for (int j=1;j<=a.m;j++)                for (int k=1;k<=m;k++)                    tmp.p[i][j]^=(p[i][k]*a.p[k][j]);        return tmp;    }    unsigned int size()    {        unsigned int ans=0;        for (int i=2;i<=n;i++)            ans=(ans<<1)+p[i][1];        return ans;    }    void print()    {        cout<<n<<' '<<m<<endl;        for (int i=1;i<=n;i++) {            for (int j=1;j<=m;j++) cout<<p[i][j]<<' ';            cout<<endl;        }    }}A,B;int n,S1,S2;int a[50],b[50],x[50],y[50];unsigned int X,Y,lim,ans,A1,B1;map < unsigned int , int > Map;void origin(){A1=0,B1=0;    A=matrix(n+1,n+1);    A.p[1][1]=1;    for (int i=1;i<=n-1;i++)         A.p[i+1][i+2]=1;    for (int i=1;i<=S1;i++)        A.p[n+1][a[i]+1]=1,A1|=(1LL<<(n-a[i]));    B=matrix(n+1,n+1);    B.p[1][1]=1;    for (int i=1;i<=n;i++)        B.p[i+1][i+1]=1;    for (int i=1;i<=S2;i++)        B.p[b[i]+1][1]=1,B1|=(1LL<<(n-b[i]));    A=B*A;    X=0;    for (int i=1;i<=n;i++) X=(X<<1)+x[i];    Y=0;    for (int i=1;i<=n;i++) Y=(Y<<1)+y[i];}void baby(){    Map.clear();    Map[Y]=0;    unsigned int X=Y;    unsigned int mo=(1LL<<n)-1;    for (int i=1;i<=lim;i++) {        unsigned int y=((((long long)X)<<1)&(mo));        for (int j=1;j<=S1;j++)        if ((X>>(n-a[j]))&1) y^=1;        y^=B1;        X=y;        Map[y]=i;    }}matrix fgm(matrix b,int e){matrix sum(b.n,b.m);for (int i=1;i<=sum.n;i++)  sum.p[i][i]=1;for (;e;e>>=1) {if (e&1) sum=sum*b;b=b*b;}return sum;}int gaint(){    matrix tmp=matrix(X,n+1,1);    A=fgm(A,(lim+1));    B=A;    for (int i=1;(lim+1)*i-lim<=(1LL<<n);i++) {        matrix tt=B*tmp;        unsigned int y=tt.size();        if (Map.count(y)) {            ans=(lim+1)*i-Map[y];            return 1;        }        B=A*B;    }    return 0;}int main(){freopen("input.txt","r",stdin);    for (;scanf("%d%d%d",&n,&S1,&S2)==3;) {        for (int i=1;i<=S1;i++) scanf("%d",&a[i]);        for (int i=1;i<=S2;i++) scanf("%d",&b[i]);        for (int i=1;i<=n;i++) scanf("%d",&x[i]);        for (int i=1;i<=n;i++) scanf("%d",&y[i]);        origin();        if (X==Y) {        printf("0\n");        continue;        }        lim=(int)sqrt((double)(1LL<<n))+1;        baby();        ans=0;        if (gaint()) cout<<ans<<endl;        else printf("poor sisyphus\n");    }    return 0;}


0 0
原创粉丝点击