抽球游戏(fwt)
地址:https://nanti.jisuanke.com/t/26017
分析:
现在是给定p,求是否存在这样的数列c,我们可以让p进行fwt变换,然后把点值都三次方根,然后再把得到的点值ufwt成系数
这题主要是判断无解的情况:
1、开三次方根后不是整数
2、最后得到的系数中有负数或者和不为给定的n
3、最后ufwt的过程中出现了非整数

1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=64; 4 int a[maxn+5]; 5 int n; 6 void fwt(int *a,int n) 7 { 8 for(int d=1;d<n;d<<=1) 9 for(int m=d<<1,i=0;i<n;i+=m) 10 for(int j=0;j<d;j++) 11 { 12 int x=a[i+j],y=a[i+j+d]; 13 a[i+j]=x+y,a[i+j+d]=x-y; 14 } 15 } 16 bool ufwt(int *a,int n) 17 { 18 for(int d=1;d<n;d<<=1) 19 for(int m=d<<1,i=0;i<n;i+=m) 20 for(int j=0;j<d;j++) 21 { 22 int x=a[i+j],y=a[i+j+d]; 23 // printf("%d %d\n",i+j,i+j+d); 24 if((x+y)%2!=0) return 0; 25 if((x-y)%2!=0) return 0; 26 a[i+j]=(x+y)/2,a[i+j+d]=(x-y)/2; 27 } 28 return 1; 29 } 30 bool solve() 31 { 32 fwt(a,64); 33 //for(int i=0;i<64;++i) printf("%d ",a[i]);printf("\n"); 34 for(int i=0;i<64;++i) 35 { 36 37 int type=a[i]<0; 38 int num=abs(a[i]); 39 40 //printf("%.9f\n",pow(-1,1.0/3)); 41 a[i]=round(pow(num,1.0/3)); 42 43 //printf("%d %d %d\n",i,a[i],num); 44 if(a[i]*a[i]*a[i]!=num) return 0; 45 if(type) a[i]=-a[i]; 46 } 47 //printf("ok\n"); 48 if(!ufwt(a,64)) return 0; 49 for(int i=0;i<64;++i) 50 { 51 if(a[i]<0) return 0; 52 n-=a[i]; 53 } 54 if(n!=0) return 0; 55 for(int i=0;i<64;++i) 56 for(int j=1;j<=a[i];++j) printf(" %d",i); 57 printf("\n"); 58 return 1; 59 } 60 int main() 61 { 62 int T; 63 scanf("%d",&T); 64 for(int cas=1;cas<=T;++cas) 65 { 66 printf("Case #%d:",cas); 67 scanf("%d",&n); 68 for(int i=0;i<64;++i) scanf("%d",&a[i]); 69 if(!solve())printf(" -1\n"); 70 } 71 return 0; 72 }