【CSP-S 2019模拟】题解

noipnoip组:

T1:

简单的莫比乌斯反演之后
得到
ans=T=1nnTmTf(T)ans=\sum_{T=1}^{n}\frac{n}{T}\frac m Tf(T)
其中fi=di(dB)μ(id)f_i=\sum_{d|i}{d\choose B}\mu(\frac i d)
gi=(iB)g_i={i\choose B}
f=gμ,fI=gf=g*\mu,f*\mathrm{I}=g
又有i=1n(iB)=(n+1B+1)\sum_{i=1}^n{i\choose B}={n+1\choose B+1}
于是可以愉快的杜教筛了

发现手写的哈希表还没有mapmap快。。

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
cs int RLEN=1<<20|1;
inline char gc(){
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob)?EOF:*ib++;
}
inline int read(){
	char ch=gc();
	int res=0;bool 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;
}
inline ll readl(){
	char ch=gc();
	ll res=0;bool 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;
}
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=9990017;
inline int add(int a,int b){return (a+=b)>=mod?(a-mod):a;}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return r>=mod?(r%mod):r;}
inline void Add(int&a,int b){a+=b,a>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline void Mul(int &a,int b){static ll r;r=1ll*a*b;a=(r>=mod)?(r%mod):r;}
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=3000005,len=N-5;
int fac[mod],ifac[mod];
int pr[N],tot,mu[N],f[N];
ll n,m,B;
bitset<N>vis;
inline int C(int n,int m){
	return n<m?0:mul(fac[n],mul(ifac[m],ifac[n-m]));
}
inline int Lucas(int n,int m){
	if(n<mod&&m<mod)return C(n,m);
	return mul(Lucas(n/mod,m/mod),C(n%mod,m%mod));
}
inline void init(){
	fac[0]=ifac[0]=1;
	for(int i=1;i<mod;i++)fac[i]=mul(fac[i-1],i);
	ifac[mod-1]=Inv(fac[mod-1]);
	for(int i=mod-2;i;i--)ifac[i]=mul(ifac[i+1],i+1);
	mu[1]=1;
	for(int i=2;i<=len;i++){
		if(!vis[i])pr[++tot]=i,mu[i]=mod-1;
		for(int j=1;j<=tot&&i*pr[j]<=len;j++){
			vis[i*pr[j]]=1;
			if(i%pr[j]==0)break;
			mu[i*pr[j]]=mod-mu[i];
		}
	}
	for(int i=1;i<=len;i++){
		for(int j=1,t=Lucas(i,B);i*j<=len;j++)
		Add(f[i*j],mul(t,mu[j]));
	}
	for(int i=1;i<=len;i++)Add(f[i],f[i-1]);
}
map<ll,int>s2;
inline int S(ll x){
	if(x<=len)return f[x];
	if(s2.count(x))return s2[x];
	int res=Lucas(x+1,B+1);
	for(ll i=2,nxt;i<=x;i=nxt+1){
		nxt=(x/(x/i));
		Dec(res,mul((nxt-i+1)%mod,S(x/i)));
	}
	return s2[x]=res;
}
int main(){
	#ifdef Stargazer
	freopen("lx.cpp","r",stdin);
	#endif
	n=readl(),m=readl(),B=read();
	init();	
	int res=0,now=0,last=0;
	for(ll i=1,nxt,l=min(n,m);i<=l;i=nxt+1){
		nxt=min(n/(n/i),m/(m/i));now=S(nxt);
		Add(res,mul(n/i%mod,mul(m/i%mod,dec(now,last))));
		last=now;
	}
	cout<<res;
}

T2:

这个区间的限制很简单
jxoi2017jxoi2017颜色那道题的骚做法一样
每个区间赋一个随机值
然后用桶存一下

不过stdstd的变成树的做法也有丶意思

代码并不想写

T3:

可以维护1212个位置的状态
好像矩乘跑不过去
暴力打出来答案后用BMBM

代码并不想写

noinoi

T2:

考虑预处理g[i][j]g[i][j]表示给ii个染jj种颜色的方案
然后考虑dpdp
f[i][j]f[i][j]表示前ii层,第ii层用jj种颜色的方案数
由于颜色集合要不同
所以f[i][j](mk)g[a[i+1]][k]>f[i+1][k](kj)f[i][j]*{m\choose k}*g[a[i+1]][k]->f[i+1][k](k\not =j)
f[i][j]((mj)1)g[a[i+1]][j]>f[i+1][j]f[i][j]*({m\choose j}-1)*g[a[i+1]][j]->f[i+1][j]

虽然有组合数而模数不是质数,但是由于gg是无序的需要乘一个j!j!
就可以把组合数消去了

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
cs int RLEN=1<<20|1;
inline char gc(){
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob)?EOF:*ib++;
}
inline int read(){
	char ch=gc();
	int res=0;bool 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;
}
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;}
int mod;
inline int add(int a,int b){return (a+=b)>=mod?(a-mod):a;}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return r>=mod?(r%mod):r;}
inline void Add(int&a,int b){a+=b,a>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline void Mul(int &a,int b){static ll r;r=1ll*a*b;a=(r>=mod)?(r%mod):r;}
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=1000005,M=5005;
char xxx;
int n,m,a[N],c[N],f[M][M],g[2][M],lim,fac[M],*tmp;
char yyy;
int main(){
	n=read(),m=read(),mod=read();
	for(int i=1;i<=n;i++)a[i]=read(),chemx(lim,a[i]);
	f[0][0]=1;
	fac[0]=1;
	for(int i=1;i<=lim;i++)fac[i]=mul(fac[i-1],i);
	for(int i=1;i<=lim;i++){
		for(int j=1;j<=i;j++)
		f[i][j]=add(mul(f[i-1][j],j-1),f[i-1][j-1]);
	}
	c[1]=m;
	for(int i=2;i<=m;i++)c[i]=mul(c[i-1],m-i+1);
	int sum=1,now=0;
	for(int i=1;i<=n;i++){
		now^=1;tmp=f[a[i]];
		if(i>1)memset(g[now],0,sizeof(int)*(a[i-2]+1));
		for(int j=1;j<=a[i];j++){
			Add(g[now][j],mul(dec(mul(sum,c[j]),mul(g[now^1][j],fac[j])),tmp[j]));
		}
		sum=0;
		for(int j=1;j<=a[i];j++)Add(sum,g[now][j]);
	}
	cout<<sum<<'\n';
}

T3:

考虑是先把n1n-1个排好,再把第nn个插入
如果不是最大的一个
那么就相当于是k,1,2,...k1k,1,2,...k-1这样
次数是2k12^{k-1}

然后等比数列求和递推即可

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
cs int RLEN=1<<20|1;
inline char gc(){
	static char ibuf[RLEN],*ib,*ob;
	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
	return (ib==ob)?EOF:*ib++;
}
#define gc getchar
inline int read(){
	char ch=gc();
	int res=0;bool 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;
}
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 int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return r>=mod?(r%mod):r;}
inline void Add(int&a,int b){a+=b,a>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline void Mul(int &a,int b){static ll r;r=1ll*a*b;a=(r>=mod)?(r%mod):r;}
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);}
int inv[100005];
int main(){
	int n=read();
	inv[1]=1;
	for(int i=2;i<=n;i++)inv[i]=mul(mod-mod/i,inv[mod%i]);
	int res=0,mt=1;
	for(int i=1;i<=n;i++)Add(res,mul(mt-1,inv[i])),Mul(mt,2);
	cout<<res;
}
posted @ 2019-11-06 17:16  Stargazer_cykoi  阅读(109)  评论(0编辑  收藏  举报