多校省选模拟 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;
}
标签:省选,sum,多校,st,int,il,px,模拟,mod 来源: https://www.cnblogs.com/sitiy/p/15790047.html