zoukankan      html  css  js  c++  java
  • 【CSP-S2019模拟】题解

    T1:

    由于模10不好做
    考虑分别做模2和模5的情况
    乘起来就是总答案

    由于有0的情况
    可以区间dpdp
    枚举子区间第一个0的位置递归做
    非0区间用带权并查集判一下合法即可

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    inline char gc(){
        static char ibuf[RLEN],*ib,*ob;
        (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
        return (ob==ib)?EOF:*ib++;
    }
    #define gc getchar
    inline int read(){
        char ch=gc();
        int res=0,f=1;
        while(!isdigit(ch))f^=ch=='-',ch=gc();
        while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
        return f?res:-res;
    }
    #define ll long long
    #define re register
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    #define cs const
    #define bg begin
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    cs int mod=1e9+7;
    inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
    inline void Add(int &a,int b){(a+=b)>=mod?a-=mod:0;}
    inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
    inline void Dec(int &a,int b){(a-=b)<0?a+=mod:0;}
    inline int mul(int a,int b){return 1ll*a*b%mod;}
    inline void Mul(int &a,int b){a=1ll*a*b%mod;}
    inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
    inline int Inv(int x){return ksm(x,mod-2);}
    cs int N=105;
    int n,q,c;
    int L[N],R[N],val[N],a[N],_0[N];
    int f[N][N],g[N][N],visf[N][N],visg[N][N];
    int fa[N],v[N];
    int inv[5]={0,1,3,2,4};
    inline int find(int x){
    	if(fa[x]==x)return x;
    	int t=fa[x];
    	fa[x]=find(fa[x]);
    	v[x]=v[x]*v[t]%c;
    	return fa[x];
    }
    inline bool merge(int x,int y,int k){
    	if(!k)return false;
    	int f1=find(x),f2=find(y);
    	if(f1!=f2){
    		fa[f2]=f1,v[f2]=v[x]*inv[k]*inv[v[y]]%c;
    		return 1;
    	}
    	return v[x]*inv[k]%c==v[y];
    }
    inline int calc_g(int l,int r,vector<int> &now){
    	if(visg[l][r])return g[l][r];
    	visg[l][r]=1;
    	for(int i=l-1;i<=r;i++)fa[i]=i,v[i]=1;
    	for(int &x:now){
    		if(!merge(L[x]-1,R[x],val[x]))return g[l][r]=0;
    	}
    	int num=-1;
    	for(int i=l-1;i<=r;i++)if(find(i)==i)num++;
    	return g[l][r]=ksm(c-1,num);
    }
    inline int calc_f(int l,int r,vector<int> &now){
    	if(!now.size())return ksm(c,r-l+1);
    	if(visf[l][r])return f[l][r];
    	visf[l][r]=1;
    
    	int res=calc_g(l,r,now);
    	for(int i=l;i<=r;i++)if(!_0[i]){
    		vector<int> vl,vr;
    		for(int &x:now){
    			if(L[x]>i)vr.pb(x);
    			if(R[x]<i){
    				if(val[x]==0)return f[l][r]=res;
    				vl.pb(x);
    			}
    		}
    		Add(res,mul(calc_g(l,i-1,vl),calc_f(i+1,r,vr)));
    	}
    	return f[l][r]=res;
    }
    inline int solve(){
    	memset(_0,0,sizeof(_0));
    	for(int i=1;i<=q;i++)
    	if(val[i]!=0){
    		for(int j=L[i];j<=R[i];j++)_0[j]=1;
    	}
    	for(int i=1;i<=q;i++)
    	if(val[i]==0){
    		int fg=0;
    		for(int j=L[i];j<=R[i];j++)if(!_0[j])fg=1;
    		if(!fg)return 0;
    	}
    	vector<int> id;
    	for(int i=1;i<=q;i++)id.pb(i);
    	memset(visg,0,sizeof(visf));
    	memset(visf,0,sizeof(visg));
    	return calc_f(1,n,id);
    }
    int main(){
    	n=read(),q=read();
    	for(int i=1;i<=q;i++)L[i]=read()+1,R[i]=read()+1,a[i]=read();
    	for(int i=1;i<=q;i++)val[i]=a[i]%2;
    	c=2;int res=solve();
    	for(int i=1;i<=q;i++)val[i]=a[i]%5;
    	c=5;Mul(res,solve());
    	cout<<res;
    }
    

    T2:

    和广二集训那道有点像
    但因为当时的做法和题解不一样所以这个也没想出来
    考虑分层dpdp
    f[i][j]f[i][j]表示前ii个点,当前层有jj个的概率
    gg表示到当前距离的期望
    枚举每个状态考虑最后一个接在哪里即可

    #include<bits/stdc++.h>
    using namespace std;
    #define gc getchar
    inline int read(){
    	char ch=gc();
    	int res=0,f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    #undef gc
    #define pb push_back
    #define re register
    #define cs const
    #define pii pair<int,int>
    #define fi first
    #define se second
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    cs int mod=998244353;
    inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
    inline void Add(int &a,int b){(a+=b)>=mod?a-=mod:0;}
    inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
    inline void Dec(int &a,int b){(a-=b)<0?a+=mod:0;}
    inline int mul(int a,int b){return 1ll*a*b%mod;}
    inline void Mul(int &a,int b){a=1ll*a*b%mod;}
    inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
    inline int Inv(int x){return ksm(x,mod-2);}
    cs int N=405;
    int pw[N*N],tr[N][N],nt[N][N];
    int f[N][N],g[N][N],C[N][N],n,p,q;
    inline void init(){
    	pw[0]=1;
    	for(int i=1;i<=n*n;i++)pw[i]=mul(pw[i-1],q);
    	for(int i=1;i<=n;i++)
    	for(int j=1;j<=n;j++)
    	tr[i][j]=ksm(dec(1,pw[i]),j);
    	for(int i=1;i<=n;i++)
    	for(int j=1;j<=n;j++)
    	nt[i][j]=pw[i*j];
    	for(int i=0;i<=n;i++){
    		C[i][i]=C[i][0]=1;
    		for(int j=1;j<i;j++)
    		C[i][j]=add(C[i-1][j-1],C[i-1][j]);
    	}
    }
    int main(){
    	n=read(),p=read(),q=1e6-p;
    	Mul(p,Inv(1e6)),Mul(q,Inv(1e6));
    	init();int res=0;
    	f[1][1]=1,g[1][1]=0;
    	for(int i=1;i<n;i++)
    	for(int j=1;j<=i;j++){
    		Add(res,mul(add(f[i][j],g[i][j]),dec(1,pw[j])));
    		Add(res,mul(nt[j][n-i],mul(f[i][j],1000000000%mod)));
    		for(int k=1;i+k<n;k++){
    			int now=mul(tr[j][k],mul(nt[j][n-i-k],C[n-i-1][k]));
    			Add(f[i+k][k],mul(f[i][j],now));
    			Add(g[i+k][k],mul(now,add(f[i][j],g[i][j])));
    		}
    	}
    	cout<<mul(mul(res,n-1),ksm(10,6*n*n));
    }
    

    T3:

    看错题了。。。

    由于要的是一个连通块的情况
    考虑计算强制不是一个连通块的减去
    做个背包就可以了

    #include<bits/stdc++.h>
    using namespace std;
    #define gc getchar
    inline int read(){
    	char ch=gc();
    	int res=0,f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    #undef gc
    #define pb push_back
    #define re register
    #define cs const
    #define pii pair<int,int>
    #define fi first
    #define se second
    template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
    template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
    int mod;
    inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
    inline void Add(int &a,int b){(a+=b)>=mod?a-=mod:0;}
    inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
    inline void Dec(int &a,int b){(a-=b)<0?a+=mod:0;}
    inline int mul(int a,int b){return 1ll*a*b%mod;}
    inline void Mul(int &a,int b){a=1ll*a*b%mod;}
    inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
    inline int Inv(int x){return ksm(x,mod-2);}
    cs int N=47;
    int n,ans;
    int fac[N],ifac[N],fa[N],inv[N];
    int G[N][N],val[N],cnt[N];
    inline void init(){
    	fac[0]=ifac[0]=1;
    	for(int i=1;i<N;i++)fac[i]=mul(fac[i-1],i);
    	ifac[N-1]=Inv(fac[N-1]);
    	for(int i=N-2;i;i--)ifac[i]=mul(ifac[i+1],i+1);
    	inv[0]=inv[1]=1;
    	for(int i=2;i<N;i++)inv[i]=mul(mod-mod/i,inv[mod%i]);
    }
    inline int C(int n,int m){
    	if(n<m)return 0;
    	int res=ifac[m];
    	for(int i=0;i<m;i++)
    	Mul(res,n-i);
    	return res;
    }
    vector<int> divi;
    inline int gcd(int a,int b){
    	return b?gcd(b,a%b):a;
    }
    int find(int x){
    	return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    inline void calc(){
    	int tot=0,res=1,siz=divi.size();
    	for(int i=1;i<=n;i++)Mul(res,ifac[cnt[i]]);
    	for(int &v:divi)Mul(res,inv[v]);
    	for(int i=0;i<siz;i++)fa[i]=i,val[i]=0;
    	for(int i=0;i<siz;i++){
    		int x=divi[i];
    		if(x&1)tot+=(x-1)/2;
    		else tot+=x/2-1,val[i]=1;
    	}
    	for(int i=0;i<siz;i++)
    	for(int j=i+1;j<siz;j++){
    		int g=G[divi[i]][divi[j]];
    		int a1=(divi[j]/g)&1,a2=(divi[i]/g)&1;
    		if(a1+a2==2){
    			int f1=find(i),f2=find(j);
    			fa[f1]=f2,tot+=g;
    		}
    		else if(a1+a2==0)tot+=g;
    		else if(a1)val[i]+=g;
    		else val[j]+=g;
    	}
    	for(int i=0;i<siz;i++)
    	if(find(i)!=i)val[find(i)]+=val[i];
    	for(int i=0;i<siz;i++)
    	if(find(i)==i)tot+=val[i]?val[i]-1:0,tot++;
    	Add(ans,mul(res,ksm(2,tot)));
    }
    void dfs(int res,int last){
    	if(!res)return calc();
    	if(res<last)return;
    	for(int i=last;i<=res;i++)
    	divi.pb(i),cnt[i]++,dfs(res-i,i),divi.pop_back(),cnt[i]--;
    }
    int f[N],g[N],t[N];
    int main(){
    	n=read(),mod=read();
    	init();
    	for(int i=1;i<=n;i++)
    	for(int j=1;j<=n;j++)G[i][j]=gcd(i,j);
    	for(int i=1;i<=n;i++)ans=0,dfs(i,1),f[i]=ans-1;
    	for(int i=1;i<=n;i++)for(int j=1;j<i;j++)Dec(f[i],f[j]);
    	g[0]=1,ans=0;
    	for(int i=1;i<=n;i++){
    		t[i]=dec(f[i],g[i]);
    		Add(ans,t[i]);
    		for(int j=n;j;j--){
    			for(int k=1;i*k<=j;k++)
    			Add(g[j],mul(g[j-i*k],C(add(t[i],k-1),k)));
    		}
    	}cout<<ans;
    }
    
  • 相关阅读:
    Bounded Context
    Unity3D研究院之IOS本地消息通知LocalNotification的使用(六十七)
    SVN服务器搭建和使用
    进度条
    XQuery获取节点的属性名与值
    AnimatorStateInfo
    Unity3D 中脚本执行的先后顺序
    Unity里面的自动寻路(二)
    Unity里面的自动寻路(一)
    java遍历文件夹两种方式
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328400.html
Copyright © 2011-2022 走看看