多校省选模拟 1

T1 序列

首先发现一个性质,就是一些元素是什么不重要,而是否相同才是重要的

然后可以在给定的a序列上左右添加元素,满足不是彩色序列同时计算方案数

f[i][j]表示生成了长度为 i ,互不相同的最长后缀长度为 j 的非彩色序列数

转移就考虑i+1从这 j 个中挑还是从k-j个中挑

计算答案时若a两两不同,枚举左边加了 i 个,右边加了n-m-i个,然后方案数乘起来

否则将问题转化,求所有长度为n的非彩序列中,连续m个互不相同元素的出现个数

转移与 f 类似,最后除掉\(A_{k}^{m}\)

T2 有向图

这个20%挺奇怪的,然后作用是能大概率找出有趣点,O(n)判断有趣点,满足dfs树只有树边和返祖边

这个东西我一直以为凡是dfs树就只有树边和返祖边,模了几个发现还有前向边,码完调了会儿发现还有横叉边,,,因为是有向图,就挺淦

回到题解,然后以找到的有趣点dfs,x是有趣点条件是x子树内只有一条边伸到x的祖先v,且v是有趣点

然后拿个multiset维护子树内的返祖边就行了

T3 图形

条件是\(\sum x_ic_i=0,\sum y_ic_i=0\)

还有\(\sum_{x_i>0} x_ic_i<=m,\sum_{y_i>0}y_ic_i<=m\)

然后不好维护,但是n和给的坐标都很小,所以可以二进制拆分\(\sum x_ic_i\),然后维护进位

\(dp_{d,px,py,nx,ny,p,q}\)表示第 d 位,x>0进到这一位大小为px,y>0进到这一维是py,对应的负数是nx,ny,然后\(\sum_{x_i>0} x_ic_i\)前i位是否不大于m,q同理是y

然后转移的时候状压枚举选的向量,满足选的正数和负数与各自的进位之和在第i位相等

然后凸包不能S=0,所以最后-1

代码

T1

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ll long long
const int N=1e3+5;
const int mod=1e9+7;
il int read()
{
	int s=0;
	char ch=getchar();
	while(ch>'9'||ch<'0')ch=getchar();
	while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	return s;
}
struct cz1{
	int n,m,k;
	int a[N],nxt[N];
	int tran[N][5];
	int f[N][N][5][5][5],g[N][N][5][5][5];
	il int min_(int x,int y){return x>y?y:x;}
	il void md(int &x){if(x>=mod)x-=mod;return;}
	void kmp()
	{
		int i=0,j=-1;
		nxt[0]=-1;
		while(i<=m&&j<=m)
		{
			if(j==-1||a[j+1]==a[i+1]) nxt[++i]=++j;
			else j=nxt[j];
		}
		return;
	}
	void solve()
	{
		if(k==1){cout<<n-m+1<<endl;return;}
		ll mi=n-m+1;
		for(int i=1;i<=n-m;++i) mi=mi*k%mod;
		for(int i=1;i<=m;++i) a[i]=read();
		if(k==2)
		{
			bool jd=1;
			for(int i=2;i<=m;++i) if(a[i]!=a[i-1]) jd=0;
			if(jd) mi=(mi-(n-m+1)+mod)%mod;
			cout<<mi<<endl;
			return;
		}
		kmp();
		for(int now,i=0;i<=m;++i)
			for(int j=1;j<=k;++j)
			{
				now=i;
				if(a[i+1]==j) tran[i][j]=i+1;
				else
				{
					while(now&&a[now+1]!=j) now=nxt[now];
					if(a[now+1]==j) tran[i][j]=now+1;
					else tran[i][j]=now;
				}

			}
		if(k==3)
		{
			f[0][0][0][0][0]=0,g[0][0][0][0][0]=1;
			for(int i=0;i<n;++i)
				for(int j=0,ed=min_(i,m);j<=ed;++j)
					for(int x=(i>1);x<=k;++x)
						for(int y=(i>0);y<=k;++y)
						{
							if(!g[i][j][x][y][0]) continue;
							for(int h=1;h<=k;++h)
							{
								if(x&&y&&h&&x!=y&&y!=h&&x!=h) continue;
								if(tran[j][h]==m) md(f[i+1][m][y][h][0]+=g[i][j][x][y][0]+f[i][j][x][y][0]);
								else md(f[i+1][tran[j][h]][y][h][0]+=f[i][j][x][y][0]);
								md(g[i+1][tran[j][h]][y][h][0]+=g[i][j][x][y][0]);
							}
						}
			int ans=0;
			for(int i=0;i<=m;++i)
				for(int x=1;x<=k;++x) for(int y=1;y<=k;++y)
					md(ans+=f[n][i][x][y][0]);
			cout<<(mi-ans+mod)%mod<<endl;
			return;
		}
		if(k==4)
		{
			f[0][0][0][0][0]=0,g[0][0][0][0][0]=1;
			for(int i=0;i<n;++i)
				for(int j=0,ed=min_(i,m);j<=ed;++j)
					for(int x=(i>2);x<=k;++x)
						for(int y=(i>1);y<=k;++y)
							for(int z=(i>0);z<=k;++z)
							{
								if(!g[i][j][x][y][z]) continue;
								for(int h=1;h<=k;++h)
								{
									if(x&&y&&z&&h)if(x!=y&&x!=z&&x!=h&&y!=z&&y!=h&&z!=h)continue;
									if(tran[j][h]==m) md(f[i+1][m][y][z][h]+=(g[i][j][x][y][z]+f[i][j][x][y][z])%mod);
									else md(f[i+1][tran[j][h]][y][z][h]+=f[i][j][x][y][z]);
									md(g[i+1][tran[j][h]][y][z][h]+=g[i][j][x][y][z]);
								}
							}
			int ans=0;
			for(int i=0;i<=m;++i)
				for(int x=1;x<=k;++x) for(int y=1;y<=k;++y) for(int z=1;z<=k;++z)
					md(ans+=f[n][i][x][y][z]);
			cout<<(mi-ans+mod)%mod<<endl;
			return;
		}
		cout<<mi<<endl;
		return;
	}
}a;
struct cz2{
	#define int long long
	il int min_(int x,int y){return x>y?y:x;}
	il void md(int &x){x=(x>=mod)?x-mod:x;return;}
	bool jud[402];
	int n,k,m,num;
	int a[25011],g[25011],h[25011];
	int f[25011][402],sum[25011][402],gg[25011][402];
	int fm(int x,int y){int ans=1;for(;y;y>>=1,x=x*x%mod)if(y&1)ans=ans*x%mod;return ans;}
	void solve2(int ans)
	{
		f[1][1]=k;
		for(int i=1;i<k;++i) sum[1][i]=k;
		for(int i=2;i<=n;++i)
			for(int j=1;j<k;++j)
			{
				f[i][j]=(sum[i-1][k-1]-sum[i-1][j-1]+mod)%mod;
				md(f[i][j]+=f[i-1][j-1]*(k-j+1)%mod);
				md(sum[i][j]=sum[i][j-1]+f[i][j]);
			}
		memset(sum,0,sizeof(sum));
		for(int i=1;i<=n;++i)
			for(int j=1;j<k;++j)
			{
				gg[i][j]=(sum[i-1][k-1]-sum[i-1][j-1]+mod)%mod;
				md(gg[i][j]+=gg[i-1][j-1]*(k-j+1)%mod);
				if(j>=m) md(gg[i][j]+=f[i][j]);
				md(sum[i][j]=sum[i][j-1]+gg[i][j]);
			}
		int s=0;
		for(int i=1;i<k;++i) md(s+=gg[n][i]);
		int val=1;
		for(int i=1;i<=m;++i) val=val*(k-i+1)%mod;
		cout<<(ans-s*fm(val,mod-2)%mod+mod)%mod<<endl;
		return;
	}
	void solve()
	{
		for(int i=1;i<=m;++i) a[i]=read();
		ll mi=n-m+1;
		for(int i=1;i<=n-m;++i) mi=mi*k%mod;
		for(int i=1;i<=m-k+1;++i)
		{
			memset(jud,0,sizeof(jud));
			num=0;
			for(int j=1;j<=k;++j)
				if(jud[a[j+i-1]]) break;
				else jud[a[i+j-1]]=1,++num;
			if(num==k) {cout<<mi<<endl;return;}
		}

		num=0;
		memset(jud,0,sizeof(jud));
		for(int i=1;i<=m;++i)
		{
			if(jud[a[i]]) break;
			jud[a[i]]=1,++num;
		}
		if(num==m){solve2(mi);return;}
		f[num][num]=1;
		for(int i=num;i<k;++i)sum[num][i]=1;
		for(int i=num+1;i<=n;++i)
			for(int j=1;j<k;++j)
			{
				f[i][j]=(sum[i-1][k-1]-sum[i-1][j-1]+mod)%mod;
				md(f[i][j]+=1ll*f[i-1][j-1]*(k-j+1)%mod);
				md(sum[i][j]=sum[i][j-1]+f[i][j]);
			}
		for(int i=num;i<=n;++i) for(int j=1;j<k;++j) md(g[i-num]+=f[i][j]);

		reverse(a+1,a+m+1);
		memset(f,0,sizeof(f));
		memset(jud,0,sizeof(jud));
		memset(sum,0,sizeof(sum));
		num=0;
		for(int i=1;i<=m;++i)
		{
			if(jud[a[i]]) break;
			jud[a[i]]=1,++num;
		}
		f[num][num]=1;
		for(int i=num;i<k;++i)sum[num][i]=1;
		for(int i=num+1;i<=n;++i)
			for(int j=1;j<k;++j)
			{
				f[i][j]=(sum[i-1][k-1]-sum[i-1][j-1]+mod)%mod;
				md(f[i][j]+=1ll*f[i-1][j-1]*(k-j+1)%mod);
				md(sum[i][j]=sum[i][j-1]+f[i][j]);
			}
		for(int i=num;i<=n;++i) for(int j=1;j<k;++j) md(h[i-num]+=f[i][j]);
		int ans=0;
		for(int i=0;i<=n-m;++i) md(ans+=1ll*g[i]*h[n-m-i]%mod);
		cout<<(mi-ans+mod)%mod<<endl;
		return;
	}
	#undef int 
}b;
int n,m,k;
int main()
{
	FILE* p=freopen("sequence.in","r",stdin);
	p=freopen("sequence.out","w",stdout);
	n=read(),k=read(),m=read();
	if(k<=4&&n<=1000) a.k=k,a.m=m,a.n=n,a.solve();
	else b.k=k,b.m=m,b.n=n,b.solve();
	return 0;
}

T2

#include<bits/stdc++.h>
using namespace std;
#define il inline
const int N=2e5+11;
bool jd;
bool vis[N];
int n,m;
int f[N],dep[N];
struct st_{int u,v;friend bool operator<(st_ a,st_ b){return dep[a.v]<dep[b.v];}};
vector<int> vct[N];
multiset<st_> st[N];
multiset<st_>::iterator it;
il int read()
{
	int s=0;
	char ch=getchar();
	while(ch>'9'||ch<'0') ch=getchar();
	while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	return s;
}
void dfs(int x)
{
	vis[x]=1;
	for(int v : vct[x])
	{
		if(!dep[v]) dep[v]=dep[x]+1,dfs(v);
		else if(!vis[v]) jd=1;
		if(jd) return;
	}
	vis[x]=0;
	return;
}
bool jud(int x)
{
	for(int i=1;i<=n;++i) dep[i]=0;
	dep[x]=1,jd=0,dfs(x);
	return !jd;
}
void get_f(int x)
{
	int sn=x;
	for(int v : vct[x])
		if(dep[v]>dep[x])
		{get_f(v);if(st[v].size()>st[sn].size()) sn=v;}
	st[x].swap(st[sn]);
	for(int v : vct[x])
		if(dep[v]>dep[x]&&v!=sn)
			while(st[v].size()) st[x].insert(*st[v].begin()),st[v].erase(st[v].begin());
	for(int v : vct[x]) if(dep[v]<dep[x]) st[x].insert({x,v});
	if(st[x].size())
	{
		it=st[x].begin();
		if(dep[it->v]<dep[x]) f[x]=it->v;
		++it;if(it!=st[x].end())if(dep[it->v]<dep[x]) f[x]=0;
	}
	return;
}
void solve(int x)
{
	for(int i=1;i<=n;++i) dep[i]=vis[i]=0;
	vis[x]=1,dep[x]=1;
	dfs(x),vis[x]=1,get_f(x);
//	for(int i=1;i<=n;++i) cout<<f[i]<<" "<<i<<endl;
	return;
}
void get_ans(int x)
{
	for(int v : vct[x])
		if(dep[v]>dep[x])
		{
			if(!vis[v]) vis[v]=vis[f[v]];
			get_ans(v);
		}
	return;
}
int main()
{
	FILE *p=freopen("graph.in","r",stdin);
	p=freopen("graph.out","w",stdout);
//	srand(time(0));
	int t=read();
	while(t--)
	{
		for(int i=1;i<=n;++i) f[i]=0,vct[i].clear(),vis[i]=0,st[i].clear();
		n=read(),m=read();
		for(int x,i=1;i<=m;++i)x=read(),vct[x].push_back(read());
//		for(int i=1;i<=n;++i)if(jud(i)) printf("%d ",i);
		for(int x,i=1;i<=100;++i){x=rand()%n+1;if(jud(x)){solve(x);get_ans(x);break;}}
		for(int i=1;i<=n;++i) if(vis[i]) printf("%d ",i);
		printf("\n");
	}
	return 0;
}

T3

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define int long long
const int N=10;
const int mod=998244353;
int n,m;
int x[N],y[N];
int f[32][21][21][21][21][2][2];
il void md(int &x){if(x>=mod)x-=mod;return;}
bool check(bool jd,int x){return ((x&1)==(m&1))?jd:((x&1)<(m&1));}
signed main()
{
	FILE* p=freopen("shape.in","r",stdin);
	p=freopen("shape.out","w",stdout);
	cin>>n>>m;
	for(int i=1;i<=n;++i) cin>>x[i]>>y[i];
	f[0][0][0][0][0][1][1]=1;
	for(int vx1,vx2,vy1,vy2,i=0;i<31;++i,m>>=1)for(int px=0;px<=20;++px)for(int py=0;py<=20;++py)
		for(int nx=0;nx<=20;++nx)for(int ny=0;ny<=20;++ny)
			for(int p=0;p<=1;++p)for(int q=0;q<=1;++q)
			{
				if(!f[i][px][py][nx][ny][p][q]) continue;
				for(int sta=0;sta<(1<<n);++sta)
				{
					vx1=vx2=0;
					for(int j=1;j<=n;++j) if((1<<j-1)&sta){if(x[j]>0)vx1+=x[j];else vx2-=x[j];}
					if(((vx1+px)&1)!=((vx2+nx)&1))continue;
					vy1=vy2=0;
					for(int j=1;j<=n;++j) if((1<<j-1)&sta){if(y[j]>0)vy1+=y[j];else vy2-=y[j];}
					if(((vy1+py)&1)!=((vy2+ny)&1))continue;
					md(f[i+1][(px+vx1)>>1][(py+vy1)>>1][(nx+vx2)>>1][(ny+vy2)>>1][check(p,vx1+px)][check(q,vy1+py)]+=f[i][px][py][nx][ny][p][q]);
				}
			}
	cout<<(f[31][0][0][0][0][1][1]-1+mod)%mod<<endl;
	return 0;
}
上一篇:luogu P2260 [清华集训2012]模积和 |数论分块


下一篇:AtCoder Beginner Contest 234 F - Reordering