其他分享
首页 > 其他分享> > [CTSC2017]吉夫特

[CTSC2017]吉夫特

作者:互联网

吉夫特

题解

挺水的一道题。

既然题面已经明示了这一串组合数相乘必须为奇数,我们考虑如何判断一个组合数为奇数。
因为 C x y ≡ 1   ( m o d   2 ) C_{x}^{y}\equiv 1\,(mod\,2) Cxy​≡1(mod2),根据卢卡斯定理有,
设 b i t x , i bit_{x,i} bitx,i​表示 x x x第 i i i位二进制的值,则 ∏ C b i t x , i b i t y , i = 1 \prod C_{bit_{x,i}}^{bit_{y,i}}=1 ∏Cbitx,i​bity,i​​=1。
很明显,只有当 y y y的二进制集合是 x x x的二进制集合的子集时上面的条件才成立。
所以,我们的 b b b序列必须满足 a b i o r   a b i − 1 = a b i − 1 a_{b_{i}} or\, a_{b_{i-1}}=a_{b_{i-1}} abi​​orabi−1​​=abi−1​​。

看到上式我们很快就想到了 d p dp dp,令 d p i dp_{i} dpi​为以 a i a_{i} ai​结尾的序列的方案数,然后枚举子集转移。
但我们很快发现,直接暴力做是 O ( n 2 ) O(n^2) O(n2)的,会T飞。
考虑折半, f x , y f_{x,y} fx,y​表示前9位为 x x x,后九位是 y y y的超集的 d p dp dp值之和。
每加入一个数时我们就先算出它的 d p dp dp值,再加到 f f f上。

时间复杂度 6 n 2 6^{\frac{n}{2}} 62n​。

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 300005
#define MAXM 525
#define reg register
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int,int> pii;
const int lim=(1<<9);
const int mo=1e9+7;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
	_T f=1;x=0;char s=getchar();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
	x*=f;
}
int n,a[MAXN],f[MAXM][MAXM],ans; 
inline int add(const int x,const int y){return x+y<mo?x+y:x+y-mo;}
signed main(){
	read(n);
	for(reg int i=1;i<=n;++i){
		read(a[i]);const int u=a[i]>>9,v=a[i]&(lim-1);int tmp=add(1,f[u][v]);
		for(reg int i=u^(lim-1);i;i=(i-1)&((lim-1)^u))tmp=add(tmp,f[i|u][v]);
		for(reg int i=v;i;i=(i-1)&v)f[u][i]=add(f[u][i],tmp);f[u][0]=add(f[u][0],tmp);
	}
	for(reg int i=0;i<lim;++i)ans=add(ans,f[i][0]);
	printf("%d\n",add(ans,mo-n));
	return 0;
}


谢谢!!!

标签:tmp,int,long,reg,add,夫特,CTSC2017,dp
来源: https://blog.csdn.net/Tan_tan_tann/article/details/113818328