爆零赛(12.24)
来源:互联网 发布:mac启动windows 编辑:程序博客网 时间:2024/06/04 18:45
平安夜的hu测
mdzz最近就是有点颓,明知道这次成绩要上报,还是妥妥的爆了零。。。
这份题的暴力打满了就是170。。。
T1
分析:
%60
做这道题之前,要了解一些复数运算
手玩了r的1~8次方之后,发现i前面一定会有一个sqrt(7),而常数项中一定没有sqrt(7)
实际上这就是复数的计算法则:
而我们需要求的答案也是符合这个形式的(只有i前面有sqrt(7))
那我们就可以把i前面的sqrt(7)抹掉
(但是如果遇到sqrt(7)i*sqrt(7)i,我们需要替换成-7)
预处理r^23所有的a+bi中的a和b值
之后暴力搜索
这里有一个小细节:
因为状态只有01,为了降低常数,我们可以直接用二进制枚举
这是一种很重要的思想
#include<cstdio>#include<cstring>#include<iostream>#define ll long longusing namespace std;double x,y;double a[30],b[30];int num[30];bool ff=0;void cal(int i,int j,int k){ a[k]=a[i]*a[j]-7*b[i]*b[j]; //b中都有一个sqrt(7),所以要替换成-7 b[k]=b[i]*a[j]+a[i]*b[j];}int pd(int num){ double xx=0,yy=0; for (int i=0;i<24;i++) if (num&(1<<i)) xx+=a[i],yy+=b[i]; return xx==x&&yy==y;}int main(){ freopen("verlauf.in","r",stdin); freopen("verlauf.out","w",stdout); scanf("%lf%lf",&x,&y); a[0]=1.0; b[0]=0.0; a[1]=-0.5; b[1]=0.5; for (int i=2;i<30;i++) { if (i&1) cal(i-1,1,i); else cal(i/2,i/2,i); } for (int i=0;i<(1<<24);i++) //8388608 if (pd(i)) { for (int j=0;j<24;j++) if (i&(1<<j)) printf("%d ",j); break; } return 0;}
T2
T3
分析:
40%
实际上这道题的部分分比较好想
什么都别多想,直接O(nk^2)
设计状态f[i][j],表示第i位上的数字是j的方案数
枚举每一位上的数字,判断相邻两数之间的gcd
直接计数即可
#include<cstdio>#include<cstring>#include<iostream>#define ll long longusing namespace std;const ll p=1000000007;const int N=1000010;int a[N],n,K;int gcd[1002][1002];ll ans=0,f[1002][1002];int GCD(int a,int b){ int r=a%b; while (r) { a=b;b=r; r=a%b; } return b;}int main(){ freopen("geburtstag.in","r",stdin); freopen("geburtstag.out","w",stdout); for (int i=1;i<=1000;i++) for (int j=1;j<=i;j++) gcd[i][j]=gcd[j][i]=GCD(i,j); scanf("%d%d",&n,&K); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<=a[1];i++) f[1][i]=1; for (int i=2;i<=n;i++) for (int j=1;j<=a[i-1];j++) for (int k=1;k<=a[i];k++) if (gcd[j][k]<=K) f[i][k]=(f[i][k]%p+f[i-1][j]%p)%p; for (int i=1;i<=a[n];i++) ans=(ans+f[n][i]%p)%p; printf("%lld",ans); return 0;}
阅读全文