• 20170927 随单题


    随:

    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;
    }
    
  • 相关阅读:
    Linux下Mysql的odbc配置
    Android:ScaleType设置图片
    Android:@id和@+id
    Android:控件布局(线性布局)LinearLayout
    Android:控件的对象修改控件的值
    Android:为控件绑定监听器
    Android四大基本组件
    java:I/O 根据用户输入反馈信息
    java:I/O 往原文件追加内容
    java:I/O 一行一行读取和写入
  • 原文地址:https://www.cnblogs.com/Juve/p/11258073.html
Copyright © 2020-2023  润新知