原来大顺指的是暴力能拿高分啊
$T1$的$3^n$过了$19$。$T2$的$2^n n^2$过了$22$。$T3$听他们说$n^3logn$过了$2000$
(虽说我复杂度和他们是一样的但我就没过去。。。)
$T1$是原题强化,然而并不会子集卷积,打了个暴力跑路。
$T2$大概猜到了状态数很少但是并不知道原来搜索真的可以过,写了个状压(数组开大)多拿了$5$分。
$T3$的想法其实大概擦到了$60pts$的边但并没有想下去。暴力跑路。
没想到这次三暴力并不差。
T1:有限空间跳跃理论
大意:图边定向后是$DAG$的方案数。$n \le 20$
被$LNC$疯狂嘲讽。
$dp_{i|j}=\sum\limits_{i \cap j = 0}dp_i + rate_j$
$rate_j=[j内部无边](-1)^{popcnt(j)-1}$
子集卷积并卡常。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mod 1000000007 4 int n,m,e[22],dp[23][1<<21],bit[1<<21],ok[22][1<<21]; 5 int add(int&a,int b){a+=b;if(a>=mod)a-=mod;} 6 void FWT(int*a){for(int i=0;i<n;++i)for(int j=0;j<1<<n;++j)if(j&1<<i)add(a[j],a[j^1<<i]);} 7 void IFWT(int*a){for(int i=0;i<n;++i)for(int j=0;j<1<<n;++j)if(j&1<<i)add(a[j],mod-a[j^1<<i]);} 8 int main(){ 9 cin>>n>>m; 10 for(int a,b,i=1;i<=m;++i)scanf("%d%d",&a,&b),e[a-1]|=1<<b-1,e[b-1]|=1<<a-1; 11 for(int i=1;i<1<<n;++i)bit[i]=bit[i^i&-i]+1; 12 for(int i=1;i<1<<n;++i){ 13 ok[bit[i]][i]=bit[i]&1?1:mod-1; 14 for(int j=0;j<n;++j)if(i>>j&1&&e[j]&i)ok[bit[i]][i]=0; 15 } 16 for(int i=1;i<=n;++i)FWT(ok[i]); 17 dp[0][0]=1; FWT(dp[0]); 18 for(int i=0;i<n;++i)for(int j=1;i+j<=n;++j)for(int x=0;x<1<<n;++x)if(dp[i][x]&&ok[j][x]) 19 dp[i+j][x]=(dp[i+j][x]+1ll*dp[i][x]*ok[j][x])%mod; 20 IFWT(dp[n]); 21 cout<<dp[n][(1<<n)-1]; 22 }
T2:神秘代码
大意:给定$01$串$s$求有多少排列$a$满足$s_i=1$则$a_i=2a_{i-1}$或$a_{i-1}=2a_i$。若$s_i=0$则满足$a_i\neq 2a_{i-1}$且$a_{i-1}\neq 2a_i,n \le 40$
可以发现$2$倍关系构成若干链。然后每次要求取出一段特定长度的链,然后下一个位置上$ban$掉零或一或二种数。
记搜,状态压一下长度为$1,2,3,4,5,6$的链各还有几个以及$ban$掉的链的长度即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mod 1000000007 4 int cnt[7],nd[66],n,d;char c[66]; 5 struct hash_map{ 6 #define S 235711 7 int fir[S],l[S],v[S],ec,to[S]; 8 int&operator[](int x){int r=x%S; 9 for(int i=fir[r];i;i=l[i])if(to[i]==x)return v[i]; 10 l[++ec]=fir[r];fir[r]=ec;to[ec]=x;return v[ec]=-1; 11 } 12 }M[66]; 13 int sch(int o,int x,int y){//cerr<<o<<' '<<cnt[1]<<' '<<cnt[2]<<' '<<cnt[3]<<endl; 14 if(o==d+1)return 1; 15 int&ans=M[o][cnt[6]<<29|cnt[5]<<26|cnt[4]<<22|cnt[3]<<17|cnt[2]<<12|cnt[1]<<6|x<<3|y],r; 16 #define I i-j-nd[o] 17 if(ans!=-1)return ans; ans=0; 18 if(nd[o]==1){ 19 for(int i=1;i<=6;++i)for(int j=0;j<i;++j)if(r=cnt[i]-(x==i&&!j)-(y==i&&!j)) 20 cnt[i]--,cnt[j]++,cnt[I]++,ans=(ans+1ll*r*sch(o+1,j,I))%mod,cnt[i]++,cnt[j]--,cnt[I]--; 21 }else for(int i=nd[o];i<=6;++i)for(int j=0;j+nd[o]<=i;++j)if(r=cnt[i]) 22 cnt[i]--,cnt[j]++,cnt[I]++,ans=(ans+1ll*r*sch(o+1,j,0)+1ll*(r-(x==i&&!j)-(y==i&&!j))*sch(o+1,I,0))%mod,cnt[i]++,cnt[j]--,cnt[I]--; 23 return ans; 24 } 25 int main(){//freopen("code8.in","r",stdin); 26 cin>>n>>c+1; 27 if(c[1]=='0')nd[d=1]=1; 28 for(int i=1;i<n;++i){ 29 if(nd[d]==1&&c[i]=='1')d--; d++;nd[d]=1; 30 while(c[i]=='1')i++,nd[d]++; 31 if(c[i]=='0'&&nd[d]!=1)nd[++d]=1; 32 }//for(int i=1;i<=d;++i)cerr<<nd[i]<<' ';cerr<<endl; 33 for(int j=n/2+1;j<=n;++j){ 34 int r=j,c=1; 35 while(!(r&1))r>>=1,c++; 36 cnt[c]++; 37 }cout<<sch(1,0,0)<<endl; 38 }
T3:预言
鸽了。牛爷爷怎么什么都会啊。