191009NOI模拟题解

T1:

$n,q\le100$

Code：

#include<bits/stdc++.h>
#define db double
#define ll long long
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define mod 1000000007
using namespace std;
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)){res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}

int mo;

inline int add(int x,int y){x+=y;if(x>=mod) x-=mod;return x;}
inline int dec(int x,int y){x-=y;if(x<0) x+=mod;return x;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline void inc(int &x,int y){x+=y;if(x>=mod) x-=mod;}
inline void Dec(int &x,int y){x-=y;if(x<0) x+=mod;}
inline void Mul(int &x,int y){x=1ll*x*y%mod;}
inline int ksm(int a,int b){int res=1;for(;b;b>>=1,a=mul(a,a)) if(b&1) res=mul(res,a);return res;}

const int N=105;
struct info{
int l,r,x;
info(){}
info(int _l,int _r,int _x):l(_l),r(_r),x(_x){}
};
int fa[N],val[N];
int get(int x){
if(fa[x]==x) return fa[x];
int f=fa[x];
fa[x]=get(fa[x]);
val[x]=1ll*val[x]*val[f]%mo;
return fa[x];
}
int inv[N];
inline bool Union(int x,int y,int z){
int xx=get(x),yy=get(y);
if(xx!=yy){
fa[xx]=yy;
val[xx]=1ll*val[y]*inv[val[x]]*inv[z]%mo;
return 1;
}
else return 1ll*val[y]*inv[val[x]]%mo==z;
}
int f[N][N],g[N][N];
int dp1(int l,int r,vector<info>v){
if(v.empty()) return ksm(mo-1,r-l+1);
int &tmp=f[l][r];
if(~tmp) return tmp;
for(int i=l-1;i<=r;i++) fa[i]=i,val[i]=1;
for(int i=0;i<v.size();i++){
if(v[i].x==0) return tmp=0;
if(!Union(v[i].l-1,v[i].r,v[i].x)) return tmp=0;
}
int res=0;
for(int i=l-1;i<=r;i++) if(fa[i]==i) ++res;
return res=ksm(mo-1,res-1);
}
int dp2(int l,int r,vector<info>v){
if(v.empty()) return ksm(mo,r-l+1);
int &tmp=g[l][r];
if(~tmp) return tmp;
tmp=dp1(l,r,v);
for(int i=l;i<=r;i++){
int flag=1;vector<info>v1,v2;
for(int j=0;j<v.size();j++){
if(v[j].l<=i && i<=v[j].r) if(v[j].x!=0) flag=0;
if(v[j].r<i) v1.pb(v[j]);
if(v[j].l>i) v2.pb(v[j]);
}
if(!flag) continue;
inc(tmp,mul(dp1(l,i-1,v1),dp2(i+1,r,v2)));
}
return tmp;
}
vector<info>vv;
int l[N],r[N],x[N];
int n,m;
inline void file(){freopen("dist.in","r",stdin);freopen("dist.out","w",stdout);}
int main(){
mo=2;
int ans=1;
memset(f,-1,sizeof(f));memset(g,-1,sizeof(g));
for(int i=1;i<=m;i++) vv.pb(info(l[i]+1,r[i]+1,x[i]%2));
inv[1]=1;
Mul(ans,dp2(1,n,vv));
mo=5;
memset(f,-1,sizeof(f));memset(g,-1,sizeof(g));vv.clear();
for(int i=1;i<=m;i++) vv.pb(info(l[i]+1,r[i]+1,x[i]%5));
for(int i=1;i<=5;i++) inv[i]=i*i*i%5;
Mul(ans,dp2(1,n,vv));
cout<<ans<<endl;
return 0;
}


T2：考虑一张n个点的无向完全图，总共有n∗(n−1)/2条边。每条边有$\frac{p}{10^6}$的概率存在，$1-\frac{p}{10^6}$的概率不存在。

$n\le400$

$f[i][j]*(dis+1)=f[i][j]**dis+f[i][j]=e[i][j]+f[i][j]$

Code：

#include<bits/stdc++.h>
#define db double
#define ll long long
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define mod 998244353
using namespace std;
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)){res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}

inline int add(int x,int y){x+=y;if(x>=mod) x-=mod;return x;}
inline int dec(int x,int y){x-=y;if(x<0) x+=mod;return x;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline void inc(int &x,int y){x+=y;if(x>=mod) x-=mod;}
inline void Dec(int &x,int y){x-=y;if(x<0) x+=mod;}
inline void Mul(int &x,int y){x=1ll*x*y%mod;}
inline int ksm(int a,int b){int res=1;for(;b;b>>=1,a=mul(a,a)) if(b&1) res=mul(res,a);return res;}

const int N=500,INF=1e9;
int n,p;
int fac[N],ifac[N],pw[N];
inline void init_fac(){
fac[0]=ifac[0]=1;
for(int i=1;i<=n;i++) fac[i]=mul(fac[i-1],i);
ifac[n]=ksm(fac[n],mod-2);
for(int i=n-1;i;i--) ifac[i]=mul(ifac[i+1],i+1);
}
int p1[N][N],p2[N][N];
inline void init_w(){
pw[0]=1;
for(int i=1;i<=n;i++) pw[i]=mul(pw[i-1],p);
for(int i=1;i<=n;i++)
for(int j=0;j<=n;j++) p1[i][j]=ksm(dec(1,pw[i]),j);
for(int i=1;i<=n;i++)
for(int j=0;j<=n;j++) p2[i][j]=ksm(p,i*j);
}
inline int C(int n,int m){if(n<0 || m<0 || n<m) return 0;return mul(fac[n],mul(ifac[m],ifac[n-m]));}
int ans=0,f[N][N],e[N][N];
inline void file(){freopen("dist.in","r",stdin);freopen("dist.out","w",stdout);}
int main(){
init_fac();init_w();
f[1][1]=1;e[1][1]=0;
for(int i=1;i<=n-1;i++)
for(int j=1;j<=i;j++) if(f[i][j]){
for(int k=1;k<=n-i-1;k++){
int tmp=mul(p1[j][k],mul(p2[j][n-i-k],C(n-i-1,k)));
inc(f[i+k][k],mul(tmp,f[i][j]));
}
}
for(int i=1;i<=n-1;i++)
for(int j=1;j<=i;j++) if(f[i][j]){
inc(ans,mul(mul(p2[n-i][j],f[i][j]),INF%mod));
}
cout<<mul(mul(ans,n-1),ksm(10,6*n*n));
return 0;
}


T3:洛谷画画加强版，要求联通

Code：

#include<bits/stdc++.h>
#define db double
#define ll long long
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)){res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
int mod;
inline int add(int x,int y){x+=y;if(x>=mod) x-=mod;return x;}
inline int dec(int x,int y){x-=y;if(x<0) x+=mod;return x;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline void inc(int &x,int y){x+=y;if(x>=mod) x-=mod;}
inline void Dec(int &x,int y){x-=y;if(x<0) x+=mod;}
inline void Mul(int &x,int y){x=1ll*x*y%mod;}
inline int ksm(int a,int b){int res=1;for(;b;b>>=1,a=mul(a,a)) if(b&1) res=mul(res,a);return res;}

const int N=105;
inline int Gcd(int a,int b){return b==0?a:Gcd(b,a%b);}
int n,ans;
int fac[N],ifac[N],inv[N],gcd[N][N];
inline void init_fac(){
fac[0]=ifac[0]=1;
for(int i=1;i<=n;i++) fac[i]=mul(fac[i-1],i);
ifac[n]=ksm(fac[n],mod-2);
for(int i=n-1;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(inv[mod%i],(mod-mod/i));

for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) gcd[i][j]=Gcd(i,j);
}
vector<int>dv;
int cnt[N],fa[N],val[N];
int get(int x){return x==fa[x]?x:fa[x]=get(fa[x]);}

inline void calc(){
int coef=1,tot=0;
for(int i=1;i<=n;i++) Mul(coef,ifac[cnt[i]]);
for(int &x:dv) Mul(coef,inv[x]);
int siz=dv.size();
for(int i=0;i<siz;i++) fa[i]=i,val[i]=0;
for(int i=0;i<siz;i++){
int x=dv[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=gcd[dv[i]][dv[j]];
int x=(dv[j]/g)&1,y=(dv[i]/g)&1;
if(x+y==2){
int f1=get(i),f2=get(j);
fa[f1]=f2;tot+=g;
}
else if(x+y==0) tot+=g;
else if(x==1) val[i]+=g;
else val[j]+=g;
}
for(int i=0;i<siz;i++) if(get(i)!=i) val[get(i)]+=val[i];
for(int i=0;i<siz;i++) if(get(i)==i) tot+=val[i]?val[i]-1:0,tot++;
inc(ans,mul(coef,ksm(2,tot)));
}
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;
}
void dfs(int v,int mx){
if(!v) return calc();
if(v<mx)return;
for(int i=mx;i<=v;i++){
cnt[i]++,dv.pb(i);
dfs(v-i,i);
cnt[i]--,dv.pop_back();
}
}
int f[N],g[N],s[N];
int main(){
init_fac();
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++){
s[i]=dec(f[i],g[i]);inc(ans,s[i]);
for(int j=n;j;j--)
}
cout<<ans;
return 0;
}


03-20 311

11-30 3484

09-13 1647

04-01 998

01-18 1237

10-20 2万+

09-29 4577

02-23 7523

10-10 2万+

08-23 1074

并查集

©️2020 CSDN 皮肤主题: 书香水墨 设计师: CSDN官方博客

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、C币套餐、付费专栏及课程。