一年补一题,一题补一年(2)| [省选联考 2024] 重塑时光
MatrixGroup · · 个人记录
题目链接
先考虑说假如我们有
那我们现在不考虑段而考虑划分。对于一个划分
考虑这个合法性是什么。其实就是把
设
为
下面是
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0,del##i##verme=int(n);i<del##i##verme;++i)
#define rep1(i,n) for(int i=1,parano##i##a=int(n);i<=parano##i##a;++i)
#define per(i,n) for(int i=int(n)-1;i>=0;--i)
#define per1(i,n) for(int i=int(n);i>=1;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define y0 LingLuo
#define y1 VividCycle
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using namespace std;
const ll mod2=1000000007;
int n,m,K,u,v;
bool ok[32768];
int to[19],fr[19];
ll fac[255],ivf[255];
ll f[33333];
ll h[16][33333],g[16][33333];
ll answer;
bool cur[33333];
int lg[333333];
int main()
{
cin>>n>>m>>K;
fac[0]=1;rep1(i,60)fac[i]=fac[i-1]*i%mod2;
ivf[60]=279203279;per(i,60)ivf[i]=ivf[i+1]*(i+1)%mod2;
rep(i,m)
{
cin>>u>>v;--u;--v;to[u]|=1<<v;fr[v]|=1<<u;
}
rep(i,n) lg[1<<i]=i;
f[0]=1;
rep1(i,(1<<n)-1)
{
rep(j,n) if((i>>j)&1) if((to[j]&i)==0) f[i]+=f[i&~(1<<j)];
f[i]%=mod2;
}
h[0][0]=mod2-1;
rep1(i,n)
{
rep(j,1<<n) if(h[i-1][j])
{
if(h[i-1][j]<0)h[i-1][j]+=mod2;
for(int k=(j+1)|j;k<(1<<n);k=(k+1)|j)
{
int rest=k^j;
if(rest==0) cur[rest]=true;
else if((rest&(rest-1))==0) cur[rest]=((j&(to[lg[rest]]|fr[lg[rest]]))==0);
else cur[rest]=cur[rest&(rest-1)]&&cur[rest&-rest];
if(cur[rest])
if((rest&-rest)==(k&-k))
{
h[i][k]=(h[i][k]-h[i-1][j]*f[rest])%mod2;
}
}
}
}
rep(j,1<<n) if(h[n][j]<0) h[n][j]+=mod2;
g[0][0]=1;
rep(i,n)
{
rep(j,1<<n) if(g[i][j])
{
for(int k=j;k<(1<<n);k=(k+1)|j)
{
int rest=k^j;
if(rest==0) cur[rest]=true;
else if((rest&(rest-1))==0) cur[rest]=((j&(to[lg[rest]]))==0);
else cur[rest]=cur[rest&(rest-1)]&&cur[rest&-rest];
if(cur[rest])
{
for(int l=i+1;l<=n;++l)
{
g[l][k]=(g[l][k]+g[i][j]*h[l-i][rest])%mod2;
}
}
}
}
}
rep1(i,min(K+1,n))
{
answer=(answer+g[i][(1<<n)-1]*ivf[K+1-i])%mod2;
}
cout<<answer*fac[K]%mod2*fac[K+1]%mod2*ivf[n+K]%mod2<<endl;
return 0;
}
/* things to check
1. int overflow or long long memory need
2. recursion/array/binary search/dp/loop bounds
3. precision
4. special cases(n=1,bounds)
5. delete debug statements
6. initialize(especially multi-tests)
7. = or == , n or m ,++ or -- , i or j , > or >= , < or <=
8. keep it simple and stupid
9. do not delete, use // instead
10. operator priority
11. is there anything extra to output?
12. ...
*/
/* something to think about
1. greedy? dp? searching? dp with matrix/ segment tree? binary search?
2. If contains "not", why not ?????? or few affect?
*/