【TJOI2019 Day1】简要题解

T1:

传送门
傻逼题,一个裸的矩乘就完了

#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
const int mod=1e9+7;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline void Add(int &a,int b){a=add(a,b);}
inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
inline void Dec(int &a,int b){a=dec(a,b);}
inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,a=mul(a,a))(b&1)?(res=mul(res,a)):0;return res;}
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
struct mat{
	int a[26][26];
	mat(){memset(a,0,sizeof(a));}
	friend inline mat operator *(cs mat &a,cs mat &b){
		mat c;
		for(int i=0;i<26;i++)
		for(int k=0;k<26;k++)
		for(int j=0;j<26;j++)
		Add(c.a[i][j],mul(a.a[i][k],b.a[k][j]));
		return c;
	}
};
inline mat ksm(mat a,ll b){
	mat res;
	for(int i=0;i<26;i++)res.a[i][i]=1;
	for(;b;b>>=1,a=a*a)if(b&1)res=res*a;
	return res;
}
mat got;
ll n;
int res;
char s[100005];
int main(){
	cin>>n;
	scanf("%s",s+1);
	for(int i=0;i<26;i++)for(int j=0;j<26;j++)got.a[i][j]=1;
	for(int i=1,len=strlen(s+1);i<len;i++){
		got.a[s[i]-'a'][s[i+1]-'a']=0;
	}
	got=ksm(got,n-1);
	for(int i=0;i<26;i++)
	for(int j=0;j<26;j++)
	Add(res,got.a[i][j]);
	cout<<res;
}

T2:

传送门
傻逼题,一个裸的平衡树就完了
不过fhqtreapfhq-treap很容易TT
splaysplay会快很多

#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
#define uint unsigned int
const int mod=1e9+7;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline void Add(int &a,int b){a=add(a,b);}
inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
inline void Dec(int &a,int b){a=dec(a,b);}
inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,a=mul(a,a))(b&1)?(res=mul(res,a)):0;return res;}
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
cs int N=2000005;
int n,m;
uint seed,last=7;
namespace RAND{
	typedef unsigned int ui;
	inline ui Rand() {
	    seed = seed * 17 + last;
	    return seed % m + 1;
	}
}
using RAND::Rand;
namespace treap{
	int son[N][2],siz[N],key[N],rt,tot;
	pii val[N];
	#define lc(u) son[u][0]
	#define rc(u) son[u][1]
	int sd=233;
	inline int rnd(){
		return sd=int(sd*482711ll%2147483647);
	}
	inline void init(){
		for(int i=1;i<N;i++)key[i]=rnd();	
	}
	inline void clear(){
		rt=tot=0;
	}
	inline int newnode(pii k){
		int u=++tot;siz[u]=1,lc(u)=rc(u)=0,val[u]=k;
		return u;
	}
	inline void pushup(int u){
		siz[u]=siz[lc(u)]+siz[rc(u)]+1;
	}
	inline void split(int r1,int &a,int &b,pii k){
		if(r1==0){a=b=0;return;}
		if(val[r1]<=k){
			a=r1,split(rc(r1),rc(a),b,k);
		}
		else b=r1,split(lc(r1),a,lc(b),k);
		pushup(r1);
	}
	inline void merge(int &r1,int a,int b){
		if(!a||!b){r1=a+b;return;}
		if(key[a]<key[b]){r1=a,merge(rc(r1),rc(a),b);}
		else r1=b,merge(lc(r1),a,lc(b));
		pushup(r1);
	}
	inline void insert(pii k){
		int u=newnode(k),r1,r2;
		split(rt,r1,r2,k);
		merge(r1,r1,u);
		merge(rt,r1,r2);
	}
	inline void delet(pii k){
		int r1,r2,r3;
		split(rt,r1,r2,pii(k.fi,k.se-1));
		split(r2,r2,r3,k);
		merge(r2,lc(r2),rc(r2));
		merge(r1,r1,r2);
		merge(rt,r1,r3);
	}
	inline int getrk(pii k){
		int r1,r2;
		split(rt,r1,r2,pii(k.fi,k.se-1));
		int res=siz[r1];
		merge(rt,r1,r2);return res;
	}
}
pii p[N];
int main(){
	int T=read();
	treap::init();
	while(T--){
		treap::clear();
		m=read(),n=read(),seed=read();
		//for(int i=1;i<=m;i++)treap::insert(p[i]);
		for(int i=1;i<=n;i++){
			int x=Rand(),y=Rand();
			if(p[x].fi)treap::delet(p[x]);
			p[x].fi--,p[x].se+=y;
			treap::insert(p[x]);
			cout<<(last=treap::getrk(p[x]))<<'\n';
		}
		for(int i=1;i<=m;i++)p[i]=pii(0,0);
	}
}

T3:

传送门
律师函警告

一个显然的思路是求出至少kk组讨论cxkcxk的方案后容斥
考虑这kk组人位置的方案数显然是(n3kk){n-3k\choose k}

然后考虑剩下的怎么放
对每种人构建EGF:f(x)=i=0akxii!EGF:f(x)=\sum_{i=0}^{a-k}\frac{x^i}{i!}
NTTNTT直接乘起来取n4kn-4k次项就是了
模数很友好

好像直接暴力卷积都可以过QwQQwQ

#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
#define uint unsigned int
#define poly vector<int>
const int mod=998244353,G=3;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline void Add(int &a,int b){a=add(a,b);}
inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
inline void Dec(int &a,int b){a=dec(a,b);}
inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,a=mul(a,a))(b&1)?(res=mul(res,a)):0;return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
cs int N=1005;
int fac[N],ifac[N],s[N],g[N][N],f[N],ans[N];
int n,a,b,c,d,mx;
int rev[N<<2];
poly w[14];
inline void init_w(){
	cs int C=13;
	for(int i=1;i<=C;i++)w[i].resize(1<<(i-1));
	int wn=ksm(G,(mod-1)/(1<<C));
	w[C][0]=1;
	for(int i=1;i<=(1<<(C-1));i++)w[C][i]=mul(w[C][i-1],wn);
	for(int i=C-1;i;i--)
	for(int j=0;j<(1<<(i-1));j++)
	w[i][j]=w[i+1][j<<1];
}
inline void init_rev(int lim){
	for(int i=0;i<lim;i++)rev[i]=(rev[i>>1]>>1)|((i&1)*(lim>>1));
}
inline void ntt(poly &f,int lim,int kd){
	for(int i=0;i<lim;i++)if(i>rev[i])swap(f[i],f[rev[i]]);
	for(int mid=1,l=1,a0,a1;mid<lim;mid<<=1,l++)
	for(int i=0;i<lim;i+=(mid<<1))
	for(int j=0;j<mid;j++)
	a0=f[i+j],a1=mul(w[l][j],f[i+j+mid]),f[i+j]=add(a0,a1),f[i+j+mid]=dec(a0,a1);
	if(kd==-1){
		reverse(f.bg()+1,f.bg()+lim);
		for(int i=0,inv=Inv(lim);i<lim;i++)Mul(f[i],inv);
	}
}
inline void init(){
	cs int len=N-5;
	fac[0]=ifac[0]=1;
	for(int i=1;i<=len;i++)fac[i]=mul(fac[i-1],i);
	ifac[len]=Inv(fac[len]);
	for(int i=len-1;i;i--)ifac[i]=mul(ifac[i+1],i+1);
}
inline int C(int n,int m){
	return n<m?0:mul(fac[n],mul(ifac[m],ifac[n-m]));
}
inline int calc(int x){
	int res=C(n-3*x,x),lim=1;
	poly A,B,C,D;
	for(int i=0;i<=a-x;i++)A.pb(ifac[i]);
	for(int i=0;i<=b-x;i++)B.pb(ifac[i]);
	for(int i=0;i<=c-x;i++)C.pb(ifac[i]);
	for(int i=0;i<=d-x;i++)D.pb(ifac[i]);
	int deg=A.size()+B.size()+C.size()+D.size()-3;
	while(lim<deg)lim<<=1;
	init_rev(lim);
	A.resize(lim),ntt(A,lim,1);
	B.resize(lim),ntt(B,lim,1);
	C.resize(lim),ntt(C,lim,1);
	D.resize(lim),ntt(D,lim,1);
	for(int i=0;i<lim;i++)A[i]=1ll*A[i]*B[i]%mod*C[i]%mod*D[i]%mod;
	ntt(A,lim,-1),A.resize(deg);
	return mul(res,mul(A[n-4*x],fac[n-4*x]));
}
int main(){
	init(),init_w();
	n=read(),a=read(),b=read(),c=read(),d=read(),mx=min(min(a,b),min(c,d)),mx=min(mx,n/4);
	for(int i=0;i<=mx;i++){
		f[i]=calc(i);
	}
	int res=0;
	for(int j=0;j<=mx;j++)
	if(j&1)Dec(res,f[j]);
	else Add(res,f[j]);
	cout<<res;
}

posted @ 2019-09-03 13:01  Stargazer_cykoi  阅读(90)  评论(0编辑  收藏  举报