今天下午考试被FFT和数论题目翔了一脸QAQ
做的是Newscafe杯的题目
第一题 异化多肽
显然构造多项式f
答案是f+f^2+f^3……
化简一下得1/(1-f)
之后多项式求逆即可
考试的时候推了好久的多项式求逆的式子(感觉自己什么都忘光了
#include<cstdio> #include<cstring> #include<iostream> #include<cstdlib> #include<algorithm> #define G 5 using namespace std; typedef long long LL; const int maxn=300010; const int mod=1005060097; int n,m,k,N,L; int A[maxn],B[maxn]; int rev[maxn]; void read(int &num){ num=0;char ch=getchar(); while(ch<‘!‘)ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘)num=num*10+ch-‘0‘,ch=getchar(); } int pow_mod(int v,int p){ int tmp=1; while(p){ if(p&1)tmp=1LL*tmp*v%mod; v=1LL*v*v%mod;p>>=1; }return tmp; } void FFT(int *A,int n,int flag){ for(L=0;(1<<L)<n;++L); for(int i=0;i<n;++i)rev[i]=rev[i>>1]>>1|((i&1)<<(L-1)); for(int i=0;i<n;++i)if(i<rev[i])swap(A[i],A[rev[i]]); for(int k=2;k<=n;k<<=1){ int mk=(k>>1); int wn=pow_mod(G,flag==1?(mod-1)/k:(mod-1)-(mod-1)/k); for(int i=0;i<n;i+=k){ int w=1; for(int j=0;j<mk;++j){ int x=A[i+j],y=1LL*A[i+j+mk]*w%mod; A[i+j]=x+y;if(A[i+j]>=mod)A[i+j]-=mod; A[i+j+mk]=x-y;if(A[i+j+mk]<0)A[i+j+mk]+=mod; w=1LL*w*wn%mod; } } } if(flag==-1){ int inv=pow_mod(n,mod-2); for(int i=0;i<n;++i)A[i]=1LL*A[i]*inv%mod; }return; } void Get_inv(int n){ if(n==1){ B[0]=pow_mod(A[0],mod-2); return; } int now=(n>>1); Get_inv(now); static int tmp[maxn]; for(int i=0;i<now;++i)tmp[i]=A[i]; FFT(tmp,n,1);FFT(B,n,1); for(int i=0;i<n;++i)B[i]=1LL*B[i]*(2-1LL*tmp[i]*B[i]%mod+mod)%mod; FFT(B,n,-1); memset(B+now,0,sizeof(int)*now); } int main(){ freopen("polypeptide.in","r",stdin); freopen("polypeptide.out","w",stdout); read(n);read(m); for(int i=1;i<=m;++i){ read(k); if(k<=n)A[k]++; }A[0]--;if(A[0]<0)A[0]+=mod; for(N=1;N<=n;N<<=1);N<<=1; Get_inv(N); int ans=-B[n]; ans=(ans%mod+mod)%mod; printf("%d\n",ans); return 0; }
第二题正解是用圆周卷积优化计算过程,也要写FFT
但是考试的时候没有看出来,于是就手写了一发bitset
结果压位大法好,暴力出奇迹
开O2的情况A掉了全部的数据QAQ
然而至今不能看懂题解
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> #define fastcall __attribute__((optimize("-O3"))) #define IL __inline__ __attribute__((always_inline)) using namespace std; typedef long long LL; const int maxn=100010; int m,n,blo,k,lim,QAQ,TAT; int ans=0x7fffffff; char s[maxn]; LL A[maxn],B[maxn],S; int L[maxn],R[maxn]; int Ans[maxn]; int Num[2000010]; int Q[maxn]; fastcall IL int Get_Num(LL v){ int sum=Num[v&lim];v>>=20; sum+=Num[v&lim];v>>=20; sum+=Num[v&lim];return sum; } fastcall IL void check(int S){ int sum=Get_Num(S); int A=(S>>(m+1)&1),B=(S>>m&1);B^=1; int tmp=(S&QAQ); int now=(2*B-1)*tmp%n; if(now<0)now+=n; if(A==0)sum+=Ans[now]; else sum+=(n-Ans[now]); if(sum<ans)ans=sum; } int main(){ freopen("virus.in","r",stdin); freopen("virus.out","w",stdout); scanf("%d%d",&m,&n);blo=60; k=(n%blo==0?n/blo:n/blo+1);lim=(1<<20)-1;QAQ=(1<<m)-1; for(int i=0;i<(1<<20);++i)Num[i]=Num[i>>1]+(i&1); scanf("%s",s+1); for(int i=1;i<=k;++i)L[i]=(i-1)*blo+1,R[i]=min(n,i*blo); for(int i=1;i<=k;++i){ for(int j=L[i];j<=R[i];++j)A[i]=A[i]<<1|(s[j]-‘0‘); } scanf("%s",s+1); for(int i=1;i<=k;++i){ for(int j=L[i];j<=R[i];++j)B[i]=B[i]<<1|(s[j]-‘0‘); } for(int i=0;i<n;++i){ int now=0; for(int j=1;j<=k;++j)now+=Get_Num(A[j]^B[j]); Ans[i]=now;now=(A[k]&1); for(int j=1;j<=k;++j){ int tmp=(A[j]&1); int len=R[j]-L[j]; A[j]>>=1; if(now)A[j]|=(1LL<<len); now=tmp; } } int up=(1<<(m+2)); for(int i=0;i<up;++i)check(i); printf("%d\n",ans); return 0; }
第三题是个数论题
推导的式子很长
最后推导的结论是R(i)+i是积性的
然后就很好搞了QAQ
至于式子嘛,明天再补上(挖坑ing)(其实是因为并不会用编辑器写公式)
吐槽一下std,花式整数溢出啊,导致造的数据都是错的
考试的时候没有看出那个性质,于是只能写O(n^2)的暴力
正准备分块打表的时候吕老师问我做完了没有,我想了想反正分块打表也没有什么意思
就直接拿到数据测了QAQ
如果分块打表的话这道题目是50分QAQ直接暴力是20分
(然而正确的数据其实只有5个)
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cstdlib> #include<cmath> using namespace std; const int maxn=1000010; const int mod=1005060097; typedef long long LL; LL n,ans,inv; int mu[maxn]; int p[maxn],cnt=0; bool vis[maxn]; LL pow_mod(LL v,int p){ LL tmp=1; while(p){ if(p&1)tmp=tmp*v%mod; v=v*v%mod;p>>=1; }return tmp; } void Get_Prime(){ mu[1]=1; for(int i=2;i<=1000000;++i){ if(!vis[i]){ p[++cnt]=i; mu[i]=-1; } for(int j=1;j<=cnt;++j){ if(1LL*i*p[j]>1000000)break; int ip=i*p[j]; vis[ip]=true; if(i%p[j]==0)break; mu[ip]=-mu[i]; } }return; } LL Get_mod(LL n){return n%mod;} LL Get_ans(LL n){ LL la,sum=0; for(LL i=1;i<=n;i=la+1){ LL now=n/i; la=n/now; sum=sum+Get_mod(la+i)*Get_mod(la-i+1)%mod*inv%mod*Get_mod(n/i)%mod; if(sum>=mod)sum-=mod; }return sum; } int main(){ freopen("function.in","r",stdin); freopen("function.out","w",stdout); scanf("%lld",&n); Get_Prime();inv=pow_mod(2LL,mod-2); int lim=(int)(sqrt(n)); for(int i=1;i<=lim;++i){ ans=ans+1LL*mu[i]*i*Get_ans(n/i/i)%mod; if(ans<0)ans+=mod; if(ans>=mod)ans-=mod; } ans=ans-Get_mod(n)*Get_mod(n+1)%mod*inv%mod; if(ans<0)ans+=mod; if(ans>=mod)ans-=mod; printf("%lld\n",ans); return 0; }
明天就要去thusc报道了
希望自己能有个好成绩吧
感觉自己还是学的太少,写的太少,想的太少
以后不能继续颓下去了QAQ
时间: 2024-10-13 13:14:19