"PKUWC 2018" Random Algorithm (60-point subsection)

 

    Tomorrow is CTSC's DAY 2 qwq, I'll save RP by knocking violently at night, and I decided to read a question casually and it's fighting violence hhhhh

    The first 50% O(3^N) violence is nothing to say, we set F[S][s] to be the point in the set S that has been selected, and the largest independent set of points in this set is the number of solutions of s, and finally After counting the inverse element multiplied by n! (s must be a subset of S, so the complexity is 3^n)

    However, the violent points among the geese will only be chained. . . . .

 

    First of all, if n is an odd number, then the largest independent set can only be all odd points. In this case, we know what the independent set is when we know the set of selected points, so we can directly O(2^n) dp . . . .

    But the author of the question is not so conscientious 2333, the n of this point is an even number in the final data. . . .

 

    Consider the case that if n is even, the independent set can only be: all odd points or all even points or ∑ [i is even] <=i all odd points and >i all even points In this case, we first use the same method as finding n is odd (the maximum independent set is all odd points) to find the answer for each even i, the maximum independent set is the odd number of points <= i, and then roll It's good to combine the integration, because the set of all even-numbered points in the back can be regarded as the reverse set of all odd-numbered points. 

    When merging, it is also multiplied by a combination number, because the order between the elements on both sides has not been determined,

 

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=300005,ha=998244353;
inline int add(int &x,int y){ x+=y; if(x>=ha) x-=ha;}
inline int ksm(int x,int y){ int an=1; for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha; return an;}
unordered_map<int,int> f[maxn];
unordered_map<int,int>:: iterator it;
int n,ci[35],m,uu,vv,BC[maxn],ans,M;
bool G[35][35],can[maxn][23];
inline int ADD(int S,int x){ return can[S][x]?(S|ci[x]):S;}
int g[maxn*4+5],jc[233],C[233][233];

inline void init(){
	for(int i=0;i<ci[n];i++)
	    for(int j=0;j<n;j++) if(!(ci[j]&i)){
	    	can[i][j]=1;
	    	for(int o=0;o<n;o++) if((ci[o]&i)&&G[o][j]){
	    		can[i][j]=0;
	    		break;
			}
			
		}
}

inline void calc(){
	ans=ans*(ll)ksm(jc[n],ha-2)%ha;
}

inline void solve(){
	f [0] [0] = 1; int all = ci [n] -1;
	
	for(int i=0;i<all;i++)
	    for(it=f[i].begin();it!=f[i].end();++it)
	        for(int j=0,S,to;j<n;j++) if(!(ci[j]&i)){
	        	S=i|ci[j],to=ADD(it->first,j),M=max(M,BC[to]);
	        	add(f[S][to],it->second);
			}
	
	for(it=f[all].begin();it!=f[all].end();++it) if(BC[it->first]==M) add(ans,it->second);
}

inline int get_line(int N){
	memset(g,0,sizeof(g));
	g [0] = 1; int all = ci [N] -1;
	
	for(int i=0;i<all;i++) if(g[i])
	    for(int j=0;j<N;j++) if(!(ci[j]&i)){
	    	if((j&1)&&!((i&ci[j-1])||(i&ci[j+1]))) continue;
	        
	        add(g[i|ci[j]],g[i]);
	    }
	return g[all];
}

inline void qwqwq(){
	int o [23];
	for(int i=2;i<=n;i+=2) o[i]=get_line(i);
	add(ans,o[n]),add(ans,o[n]);
	
	for(int i=2;i<n;i+=2) add(ans,o[i]*(ll)o[n-i]%ha*C[n][i]%ha);
}

int main(){
	ci [0] = 1;
	for(int i=1;i<=20;i++) ci[i]=ci[i-1]<<1;
	jc[0]=1;
	for(int i=1;i<=20;i++) jc[i]=jc[i-1]*(ll)i%ha;
	C[0][0]=1;
	for(int i=1;i<=75;i++){
		C[i][0]=1;
		for(int j=1;j<=i;j++) add(C[i][j],C[i-1][j-1]),add(C[i][j],C[i-1][j]);
	}
	
	scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++) scanf("%d%d",&uu,&vv),G[uu-1][vv-1]=G[vv-1][uu-1]=1;
	
	if(n<=17){
		for(int i=1;i<ci[n];i++) BC[i]=BC[i^(i&-i)]+1;    
	    init(),solve();
    }
    else if(n&1) ans=get_line(n);
    else qwqwq();

    calc();
    
	printf("%d\n",ans);
	return 0;
}

  

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325890989&siteId=291194637