以为要考图论呢,结果考了一堆不知道是啥的东西,尤其是第一题(考得是暴力枚举?质因数分解??高考数学必修5???),考试时一直以为正解是个数据结构,后来发现个数单调可以二分,然而排序时间复杂度好高啊……不管了先打个暴力,复杂度$1000*n^2*log^2n$,%了几个点都过了(最后因为复杂度过高使本来拿到的20分T了,其实只考虑q=1就有25分……),于是开始打第二题,期望?这分数好恶心啊……显然树形dp啊,
A. 序列 :这个题真的好沙雕啊,正解难打的要命而且时间复杂度也并不低(甚至有的暴力可以比他快???),暴力都能AC……更有趣的是q只需要枚举到100……
//爆0的考试代码(去掉二分有20分???) #include<algorithm> #include<iostream> #include<cstdio> #define LL long long #define max(a,b) ((a)>(b)?(a):(b)) using namespace std; int n; LL A[100010],B[100010]; LL l=1,r=100000,mid,q; LL ans,maxn; LL s(LL x,int g){while(x>=g)x/=g;return x;} bool pd(int mid) { bool pdd=1; for(int i=1;i<=1+n-mid;i++) { pdd=1; sort(B+i,B+i+mid); for(int j=i+1;j<i+mid;j++) if(B[j]!=B[j-1]*q){pdd=0;break;} for(int j=i;j<i+mid;j++) B[j]=A[j]; if(pdd){return 1;} } return 0; } inline LL read() { LL s=0;char a=getchar(); while(a<'0'||a>'9')a=getchar(); while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();} return s; } signed main() { // freopen("in.txt","r",stdin); n=read(); for(int i=1;i<=n;i++)A[i]=read(),B[i]=A[i],maxn=max(maxn,A[i]); int L=0,R=0;r=n; for(int i=1;i<=n;i++) { if(A[i]==A[i-1]&&!L)L=i-1; if(A[i]!=A[i-1]&&L)ans=max(ans,i-L),L=0; } // for(int i=1;i<=n;i++)cout<<A[i]<<" "; // puts(""); for(q=2;q<=1000&&q<maxn;q++) { l=1,r=n; while(l<=r) { mid=(l+r)>>1; if(pd(mid))ans=max(ans,mid),l=mid+1; else r=mid-1; /// cout<<q<<" "<<ans<<endl; } } printf("%lld ",ans); }
//打爆了的正解 #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<set> #include<map> #define int LL #define LL long long #define ma(x) memset(x,0,sizeof(x)) #define max(a,b) ((a)>(b)?(a):(b)) using namespace std; int n; LL A[200010]; LL l=1,r=100000,mid,q; LL ans=1,maxn; map<int,int> mp; inline LL read() { LL s=0;char a=getchar(); while(a<'0'||a>'9')a=getchar(); while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();} return s; } bool isprime[500010]; int prime[50000],cnt; void s(int maxn) { for(int i=2;i<=maxn;i++)isprime[i]=1; for(int i=2;i<=maxn;i++) { if(isprime[i]){prime[++cnt]=i;} for(int j=1;j<=cnt && i*prime[j]<=maxn;j++) { isprime[i*prime[j]]=0; if(!i%prime[j])break; } } } int zys[1000000],cf[1000000],num; void fj(int n) { num=0;ma(cf); if(n==1){zys[++num]=1,cf[num]=1;return;} for(int i=1;i<=50000&&prime[i]<=n;i++) { if(!(n%prime[i])) { zys[++num]=prime[i]; while(!(n%prime[i]))n/=prime[i],cf[num]++; } } zys[++num]=n; } LL gcd(int a,int b){return !b?a:gcd(b,a%b);} signed main() { freopen("in.txt","r",stdin); // freopen("0.out","w",stdout); n=read(); for(int i=1;i<=n;i++)A[i]=read(),maxn=max(maxn,A[i]); int L=0,R=0;r=n; for(int i=1;i<=n;i++) { if(A[i]==A[i-1]&&!L)L=i-1; if(A[i]!=A[i-1]&&L)ans=max(ans,i-L),L=i; }s(500000); if(A[n]==A[n-1])ans=max(ans,n-L+1); int x,y,z,g=1,q;bool pd=1; for(int i=1;i<n-1;i++) { g=q=1; mp.clear(); x=max(A[i],A[i+1]),y=min(A[i],A[i+1]); mp[A[i]]=1;mp[A[i+1]]=1; if(x==y)continue; if(x%y!=0)continue; z=x/y; if(z>=maxn/2){ans=max(ans,2);continue;} fj(z); for(int j=1;j<=num;j++)g=gcd(g,cf[j]); for(int j=1;j<=num;j++)q*=pow(zys[j],cf[j]/g); for(int j=i+2;j<=n;j++) if(mp.find(A[j])!=mp.end()){ans=max(ans,j-i);i=j-1;break;} else { if(max(A[j],A[j-1])%min(A[j],A[j-1])){ans=max(ans,j-i);i=j-1;break;} int te=max(A[j],A[j-1])/min(A[j],A[j-1]); pd=1; for(int k=1;;k++) { int tem=pow(q,k); if(tem==te)break; else if(tem>te){break;pd=0;} } if(!pd){ans=max(ans,j-i+1);i=j-1;break;} if(j==n)i=n; } } printf("%lld ",ans); }
RE35真的难调……
//AC的暴力 #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<set> #include<map> #define int LL #define LL long long #define ma(x) memset(x,0,sizeof(x)) #define max(a,b) ((a)>(b)?(a):(b)) using namespace std; int n; LL A[200010]; LL l=1,r=100000,mid,q; LL ans=1,maxn; map<int,int> mp; inline LL read() { LL s=0;char a=getchar(); while(a<'0'||a>'9')a=getchar(); while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();} return s; } LL gcd(int a,int b){return !b?a:gcd(b,a%b);} signed main() { // freopen("in.txt","r",stdin); // freopen("0.out","w",stdout); n=read(); for(int i=1;i<=n;i++)A[i]=read(),maxn=max(maxn,A[i]); int L=0,R=0;r=n; for(int i=1;i<=n;i++) { if(A[i]==A[i-1]&&!L)L=i-1; if(A[i]!=A[i-1]&&L)ans=max(ans,i-L),L=i; } if(A[n]==A[n-1])ans=max(ans,n-L+1); bool pd=0; for(int q=2;q<=1000;q++) { int tem=0; for(int i=1;i<=ans;i++) { tem*=q;if(q>maxn){pd=1;break;} } if(pd)break; for(int i=1;i<=n;i++) { mp.clear(); int tem=A[i]; mp[tem]=1; if(tem%q!=0&&tem>q){continue;} while(tem%q==0)tem/=q; for(int j=i+1;j<=n;j++) { int te=A[j]; if(mp.find(te)!=mp.end()){ans=max(ans,j-i);break;} if(te%q!=0&&te!=tem){ans=max(ans,j-i);break;} while(te%q==0)te/=q; if(te!=tem){ans=max(ans,j-i);break;} } } } printf("%lld ",ans); }
C. 建造游乐园(play) :这个题因为没什么思路,到最后就留了二十多分钟打表,欧拉图个数*C想到了,其实主要是欧拉图个数不会求……然后就瞎打了个组合数,WA0……
#include<iostream> #include<cstdio> #define LL long long #define mod 1000000007 using namespace std; int n; LL jc[2010]; inline int read() { int s=0;char a=getchar(); while(a<'0'||a>'9')a=getchar(); while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();} return s; } LL poww(LL a,int b); signed main() { n=read(); jc[0]=1;for(int i=1;i<=2000;i++)jc[i]=(jc[i-1]*i)%mod; if(n==1){puts("0");return 0;} if(n==2){puts("0");return 0;} if(n==3){puts("3");return 0;} if(n==9){puts("21124449");return 0;} LL num=jc[n-1]%mod*poww(2,mod-2)%mod, tem=(n-3)*n%mod*(poww(2,mod-2))%mod; LL ans=num*(n+tem)%mod; // cout<<tem<<" "<<num<<endl; printf("%lld ",ans); } LL poww(LL a,int b) { LL ans=1; while(b) { if(b&1)ans=(ans*a)%mod; a=(a*a)%mod; b=b>>1; } return ans; }
#include<iostream> #include<cstdio> #define mod 1000000007 #define LL long long #define int LL using namespace std; LL jc[2010]; int n; int f[2010],g[2010]; LL C[2010][2010]; LL poww(LL a,int b) { LL ans=1; while(b) { if(b&1)ans=(ans*a)%mod; a=(a*a)%mod; b=b>>1; } return ans; } signed main() { jc[0]=1;for(int i=1;i<=2010;i++)jc[i]=jc[i-1]*i; C[0][0]=1; for(int i=1;i<=2010;i++) { C[i][0]=1; for(int j=1;j<=2010;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; } cin>>n; for(int i=1;i<=n;i++) { f[i]=g[i]=poww(2,C[i-1][2]); for(int j=1;j<i;j++) f[i]=(f[i]-f[j]*g[i-j]%mod*C[i-1][j-1]%mod+mod)%mod; } printf("%lld ",f[n]*C[n][2]%mod); }
B. 熟练剖分(tree) :考试的时候感觉这题比其他两个题要好点(和上次考试感觉一样,他是最难的一个题……),又是一半多的时间在搞这个题,通分太难弄了呀(其实直接乘逆元就可以了),考试的时候想了个错解(还能有20分),对于每个节点记录儿子的期望的最大值和次大值:
int z[MAXN],m[MAXN]; void dfs(int x) { // cout<<x<<endl; if(!du[x]){z[x]=0,m[x]=1;return;} double max1=-1,max2=-1;int maxx1=0,maxx2=0; for(int i=f(x);i;i=n(i)) { dfs(v(i)); double tem=(double)z[v(i)]/(double)m[v(i)]; if(fabs(tem-max1)>esp) max2=max1,max1=tem,maxx2=maxx1,maxx1=v(i); else if(fabs(tem-max2)>=esp) max2=tem,maxx2=v(i); } // cout<<"!"<<x<<endl; // cout<<max1<<" "<<max2<<" "<<maxx1<<" "<<maxx2<<endl; if(du[x]==1) { z[x]=z[maxx1],m[x]=m[maxx1]; } else if(max1>max2+1) { m[x]=(m[maxx1]*du[x])%mod; z[x]=((z[maxx1]+1)*(du[x]-1)%mod+z[maxx1])%mod; } else { m[x]=(m[maxx1]*m[maxx2]%mod); z[x]=((z[maxx1]+m[maxx1])*(du[x]-1)%mod*(m[x]/m[maxx1])%mod+(z[maxx2]+m[maxx2])*(m[x]/m[maxx2]%mod))%mod; m[x]=(m[x]*du[x])%mod; } // cout<<x<<" "<<z[x]<<" "<<m[x]<<endl; }
但是期望比较大小是没有意义的啊,即使他的期望比较小但是他还是有可能出一个很大的值的……完了完了(平方的期望不是期望的平方,最大值的期望不是期望的最大值……)
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #define LL long long 5 #define MAXN 3010 6 #define esp 1e-8 7 #define mod 1000000007 8 using namespace std; 9 struct edge 10 { 11 int u,v,nxt; 12 #define u(x) ed[x].u 13 #define v(x) ed[x].v 14 #define n(x) ed[x].nxt 15 }ed[500000]; 16 int first[MAXN],num_e; 17 #define f(x) first[x] 18 int n,root; 19 int du[MAXN],ru[MAXN]; 20 21 LL poww(LL a,int b); 22 inline void add(int u,int v) 23 { 24 ++num_e; 25 u(num_e)=u; 26 v(num_e)=v; 27 n(num_e)=f(u); 28 f(u)=num_e; 29 } 30 inline int read() 31 { 32 int s=0;char a=getchar(); 33 while(a<'0'||a>'9')a=getchar(); 34 while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();} 35 return s; 36 } 37 int z[MAXN],m[MAXN]; 38 void dfs(int x) 39 { 40 // cout<<x<<endl; 41 if(!du[x]){z[x]=0,m[x]=1;return;} 42 double max1=-1,max2=-1;int maxx1=0,maxx2=0; 43 for(int i=f(x);i;i=n(i)) 44 { 45 dfs(v(i)); 46 double tem=(double)z[v(i)]/(double)m[v(i)]; 47 if(fabs(tem-max1)>esp) 48 max2=max1,max1=tem,maxx2=maxx1,maxx1=v(i); 49 else if(fabs(tem-max2)>=esp) 50 max2=tem,maxx2=v(i); 51 } 52 // cout<<"!"<<x<<endl; 53 // cout<<max1<<" "<<max2<<" "<<maxx1<<" "<<maxx2<<endl; 54 if(du[x]==1) 55 { 56 z[x]=z[maxx1],m[x]=m[maxx1]; 57 } 58 else if(max1>max2+1) 59 { 60 m[x]=(m[maxx1]*du[x])%mod; 61 z[x]=((z[maxx1]+1)*(du[x]-1)%mod+z[maxx1])%mod; 62 } 63 else 64 { 65 m[x]=(m[maxx1]*m[maxx2]%mod); 66 z[x]=((z[maxx1]+m[maxx1])*(du[x]-1)%mod*(m[x]/m[maxx1])%mod+(z[maxx2]+m[maxx2])*(m[x]/m[maxx2]%mod))%mod; 67 m[x]=(m[x]*du[x])%mod; 68 } 69 // cout<<x<<" "<<z[x]<<" "<<m[x]<<endl; 70 } 71 signed main() 72 { 73 // freopen("in.txt","r",stdin); 74 75 // cout<<(5*poww(12,mod-2))%mod<<" "<<((5+mod)*poww(mod+12,mod-2))%mod<<endl; 76 n=read();int a; 77 for(int i=0;i<=n;i++)m[i]=1; 78 for(int i=1;i<=n;i++) 79 { 80 du[i]=read(); 81 for(int j=1;j<=du[i];j++) 82 a=read(),add(i,a),ru[a]++; 83 } 84 bool pdl=1; 85 for(int i=1;i<=n;i++) 86 { 87 if(du[i]!=1&&du[i]!=0)pdl=0; 88 if(!ru[i])root=i; 89 } 90 if(pdl){puts("0");return 0;} 91 dfs(root); 92 // cout<<z[root]<<" "<<m[root]<<endl; 93 printf("%lld ",(z[root]*poww(m[root],mod-2))%mod); 94 } 95 LL poww(LL a,int b) 96 { 97 LL ans=1; 98 while(b) 99 { 100 if(b&1)ans=(ans*a)%mod; 101 a=(a*a)%mod; 102 b=b>>1; 103 } 104 return ans; 105 }