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;
}
原文地址:https://www.cnblogs.com/Juve/p/11258073.html