随:
50%有一个dp:
#include<iostream> #include<cstdio> #include<cstring> #define ll long long #define MAXN 100005 #define re register ll n,m,p,a[MAXN],num[MAXN],order[MAXN],tot=0,f[2][MAXN],ans=0,den; const ll mod=1e9+7; inline ll q_pow(re ll a,re ll b,re ll p){ re ll res=1; while(b){ if(b&1) res=(res*a)%p; a=(a*a)%p; b>>=1; } return res%p; } signed main(){ scanf("%lld%lld%lld",&n,&m,&p); if(n==1){ re ll b; scanf("%lld",&b); re ll ans=q_pow(b,m,p)%mod; printf("%lld ",ans); return 0; } if(p==2){ puts("1"); return 0; } for(ll i=1;i<=n;i++){ scanf("%lld",&a[i]); if(num[a[i]]==0) order[++tot]=a[i]; num[a[i]]++; } f[0][1]=1; for(ll i=1;i<=m;i++){ for(ll j=1;j<=p;j++) f[i&1][j]=0; for(ll j=1;j<=tot;j++){ ll ord=order[j]; ll q=num[ord]; for(ll k=1;k<p;k++) f[i&1][ord*k%p]=(f[i&1][ord*k%p]+f[i&1^1][k]*q)%mod; } } den=q_pow(n,mod-2,mod); den=q_pow(den,m,mod); for(ll i=1;i<p;i++) ans=(ans+f[m&1][i]*i)%mod; //printf("%lld %lld ",ans,den); printf("%lld ",ans*den%mod); return 0; }
100%:原根+瞎搞?
其实不用怎么做(明明是博主不会原根)
我们倍增优化这个dp,将m二进制拆分
#include<iostream> #include<cstdio> #include<cstring> #define ll long long #define MAXN 100005 #define re register ll n,m,p,a[MAXN],f[2][1005],ans=0,den,g[2][1005],nowg=1,nowf=1; const ll mod=1e9+7; inline ll q_pow(re ll a,re ll b,re ll p){ re ll res=1; while(b){ if(b&1) res=(res*a)%p; a=(a*a)%p; b>>=1; } return res%p; } signed main(){ scanf("%lld%lld%lld",&n,&m,&p); if(n==1){ re ll b; scanf("%lld",&b); re ll ans=q_pow(b,m,p)%mod; printf("%lld ",ans); return 0; } if(p==2){ puts("1"); return 0; } for(ll i=1;i<=n;i++){ scanf("%lld",&a[i]); f[0][a[i]]++; } den=q_pow(n,mod-2,mod); den=q_pow(den,m,mod); g[0][1]=1; while(m){ if(m&1){ for(ll i=0;i<=p;i++) g[nowg][i]=0; for(ll i=1;i<p;i++){ for(ll j=1;j<p;j++) g[nowg][i*j%p]=(g[nowg][i*j%p]+f[nowf^1][i]*g[nowg^1][j])%mod; } nowg^=1; } for(ll i=0;i<=p;i++) f[nowf][i]=0; for(ll i=1;i<p;i++){ for(ll j=1;j<p;j++) f[nowf][i*j%p]=(f[nowf][i*j%p]+f[nowf^1][i]*f[nowf^1][j])%mod; } nowf^=1; m>>=1; } for(ll i=1;i<p;i++) ans=(ans+g[nowg^1][i]*i)%mod; //printf("%lld %lld ",ans,den); printf("%lld ",ans*den%mod); return 0; }
单:
40%:n2暴力+n3高斯消元
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #define ll long long #define MAXN 100005 #define re register #define eps (1e-8) using namespace std; ll t,n,type,a[MAXN],b[MAXN]; bool flag=1; ll to[MAXN<<1],nxt[MAXN<<1],pre[MAXN],cnt=0; inline void add(re ll u,re ll v){ cnt++,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt; } ll f[MAXN][20],deep[MAXN]; inline void dfs(re ll x){ for(re ll i=1;i<=18;i++){ if(f[x][i-1]) f[x][i]=f[f[x][i-1]][i-1]; } for(re ll i=pre[x];i;i=nxt[i]){ if(to[i]!=f[x][0]){ deep[to[i]]=deep[x]+1; f[to[i]][0]=x; dfs(to[i]); } } } inline ll LCA(re ll x,re ll y){ if(deep[x]<deep[y]) swap(x,y); re ll k=deep[x]-deep[y]; for(re ll i=0;i<=18;i++) if((1<<i)&k) x=f[x][i]; if(x==y) return x; for(re ll i=18;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; } double g[10005][10005]; inline void gs(){ for(re ll i=1;i<=n;i++){ re ll p=i; for(re ll j=i+1;j<=n;j++) if(fabs(g[j][i])>fabs(g[p][i])) p=j; for(re ll j=1;j<=n+1;j++) swap(g[p][j],g[i][j]); if(fabs(g[i][i])<eps) continue; double tmp=g[i][i]; for(re ll j=1;j<=n+1;j++) g[i][j]/=tmp; for(re ll j=1;j<=n;j++) if(i!=j){ double temp=g[j][i]; for(re ll k=1;k<=n+1;k++) g[j][k]-=g[i][k]*temp; } } } signed main(){ scanf("%lld",&t); while(t--){ scanf("%lld",&n); for(re ll i=1,u,v;i<n;i++){ scanf("%lld%lld",&u,&v); if(v!=u+1) flag=0; add(u,v),add(v,u); } dfs(1); scanf("%lld",&type); if(type==0){ for(re ll i=1;i<=n;i++){ scanf("%lld",&a[i]); } for(re ll i=1;i<=n;i++){ for(re ll j=1;j<=n;j++){ if(i==j){ continue; } re ll lca,dis; if(flag==1) dis=abs(i-j); else{ lca=LCA(i,j); dis=deep[i]+deep[j]-2*deep[lca]; } b[i]+=a[j]*dis; } printf("%lld ",b[i]); } puts(""); }else{ for(re ll i=1;i<=n;i++){ scanf("%lld",&b[i]); g[i][n+1]=(double)b[i]; } for(re ll i=1;i<=n;i++){ for(re ll j=1;j<=n;j++){ if(i==j){ g[i][j]=0; continue; } re ll lca,dis; if(flag==1) dis=abs(i-j); else{ lca=LCA(i,j); dis=deep[i]+deep[j]-2*deep[lca]; //printf("%lld %lld ",lca,dis); } g[i][j]=(double)dis; } } gs(); for(re ll i=1;i<=n;i++){ //if(fabs(g[i][n+1])<eps) printf("0 "); //else printf("%.0lf ",g[i][n+1]); } puts(""); } memset(f,0,sizeof(f)); memset(pre,0,sizeof(pre)); //memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); cnt=deep[1]=0; flag=1; } return 0; } /* 7 1 2 1 3 2 4 2 5 4 6 4 7 10 5 1 2 1 3 2 4 2 5 0 6 8 7 1 3 5 1 2 1 3 2 4 2 5 1 23 24 34 47 43 5 1 2 1 3 2 4 2 5 0 19 2 1 14 3 5 1 2 1 3 2 4 2 5 1 37 38 74 49 71 4 1 2 2 3 3 4 0 5 7 10 8 4 1 2 2 3 3 4 1 51 31 25 39 6 1 2 1 3 1 4 2 5 2 6 0 5 7 9 1 3 2 6 1 2 1 3 1 4 2 5 2 6 1 27 30 36 52 51 53 */
100%:我能不能不在这里推式子呀?毕竟把别人提解粘过来不太好
那我就放个链接把大家骗到小红博客里:
https://www.cnblogs.com/Rorschach-XR/p/11255318.html
rp++
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<cmath> #define ll long long #define MAXN 100005 #define re register using namespace std; ll t,n,type,a[MAXN],b[MAXN]; ll to[MAXN<<1],nxt[MAXN<<1],pre[MAXN],cnt=0; inline void add(re ll u,re ll v){ cnt++,to[cnt]=v,nxt[cnt]=pre[u],pre[u]=cnt; } ll deep[MAXN],sum=0,size[MAXN];//size[i]表示i的子数中a[son]的和 void dfs_1(re ll x,re ll fa){ for(ll i=pre[x];i;i=nxt[i]){ ll y=to[i]; if(y==fa) continue; deep[y]=deep[x]+1; dfs_1(y,x); size[x]+=size[y]; } } void dfs_2(re ll x,re ll fa){ for(re ll i=pre[x];i;i=nxt[i]){ re ll y=to[i]; if(y==fa) continue; b[y]=b[x]+sum-2*size[y]; dfs_2(y,x); } } ll dt[MAXN]; void dfs_3(re ll x,re ll fa){ for(re ll i=pre[x];i;i=nxt[i]){ re ll y=to[i]; if(y==fa) continue; dt[y]=b[y]-b[x]; dfs_3(y,x); } } void dfs_4(re ll x,re ll fa){ a[x]=size[x]; for(re ll i=pre[x];i;i=nxt[i]){ re ll y=to[i]; if(y==fa) continue; dfs_4(y,x); a[x]-=size[y]; } } signed main(){ scanf("%lld",&t); while(t--){ scanf("%lld",&n); for(re ll i=1,u,v;i<n;i++){ scanf("%lld%lld",&u,&v); add(u,v),add(v,u); } scanf("%lld",&type); if(type==0){ for(re ll i=1;i<=n;i++){ scanf("%lld",&a[i]); sum+=a[i]; size[i]=a[i]; } dfs_1(1,0); for(re ll i=1;i<=n;i++) b[1]+=deep[i]*a[i]; dfs_2(1,0); for(re ll i=1;i<=n;i++) printf("%lld ",b[i]); puts(""); }else{ for(re ll i=1;i<=n;i++){ scanf("%lld",&b[i]); } dfs_3(1,0); for(re ll i=1;i<=n;i++) sum+=dt[i]; size[1]=(sum+2*b[1])/(n-1); for(re ll i=2;i<=n;i++) size[i]=(size[1]-dt[i])/2; dfs_4(1,0); for(re ll i=1;i<=n;i++) printf("%lld ",a[i]); puts(""); } memset(pre,0,sizeof(pre)); memset(deep,0,sizeof(deep)); memset(size,0,sizeof(size)); memset(dt,0,sizeof(dt)); memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); cnt=sum=0; } return 0; } /* 7 1 2 1 3 2 4 2 5 4 6 4 7 10 5 1 2 1 3 2 4 2 5 0 6 8 7 1 3 5 1 2 1 3 2 4 2 5 1 23 24 34 47 43 5 1 2 1 3 2 4 2 5 0 19 2 1 14 3 5 1 2 1 3 2 4 2 5 1 37 38 74 49 71 4 1 2 2 3 3 4 0 5 7 10 8 4 1 2 2 3 3 4 1 51 31 25 39 6 1 2 1 3 1 4 2 5 2 6 0 5 7 9 1 3 2 6 1 2 1 3 1 4 2 5 2 6 1 27 30 36 52 51 53 */
题:
3个组合数(CATALAN相关)和一个dp
#include<cstdio> #include<iostream> #include<cmath> #define ll long long #define mod 1000000007 #define MAXN 100005 using namespace std; ll n,type,ans=0,dp[MAXN]={1}; ll q_pow(ll a,ll b,ll p){ ll res=1; while(b){ if(b&1) res=(res*a)%p; a=(a*a)%p; b>>=1; } return res; } ll fac[MAXN],inv[MAXN]; void get_fac_and_inv(){ fac[0]=fac[1]=inv[0]=inv[1]=1; for(ll i=2;i<=n;i++) fac[i]=fac[i-1]*i%mod; inv[n]=q_pow(fac[n],mod-2,mod); for(ll i=n-1;i>=2;i--) inv[i]=inv[i+1]*(i+1)%mod; } void dfs(ll now,ll num){ if(num==n&&now==0){ ans++; if(ans>mod) ans-=mod; //cout<<ans<<endl; return ; } if(num==n&&now!=0) return ; if(abs(now)>(n>>1)) return ; if(abs(now)>(n-num)) return ; dfs(now+1,num+1); dfs(now-1,num+1); } ll C(ll n,ll m){ return fac[n]*inv[m]%mod*inv[n-m]%mod; } ll CATALAN(ll n){ return C(2*n,n)*q_pow(n+1,mod-2,mod)%mod; } int main(){ scanf("%lld%lld",&n,&type); get_fac_and_inv(); if(type==0){ ll m=n>>1; for(ll i=0;i<=m;i++){ ll j=m-i; ans=(ans+(fac[n]*inv[i]%mod*inv[j]%mod*inv[i]%mod*inv[j]%mod)%mod)%mod; } printf("%lld ",ans%mod); } if(type==1){ ll m=n>>1; ll invm=q_pow(m+1,mod-2,mod); ans=fac[n]*inv[m]%mod*inv[m]%mod*invm%mod; printf("%lld ",ans%mod); } if(type==2){ dp[1]=dp[0]*4; for(ll i=2;i<=n/2;i++) for(ll j=1;j<=i;j++) dp[i]=(dp[i]+dp[i-j]%mod*CATALAN(j-1)%mod*4%mod)%mod; printf("%lld ",dp[n/2]%mod); } if(type==3){ for(ll i=0;i<=n;i+=2) ans=(ans+C(n,i)%mod*CATALAN(i/2)%mod*CATALAN((n-i)/2))%mod; printf("%lld ",ans%mod); } return 0; }