可以看出这些操作是可以用一些异或实现,而异或又是满足结合律的,因此可以写成矩阵的形式
那么题目的实质就是求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;
}