码迷,mamicode.com
首页 > 其他好文 > 详细

习题:Random Elections (DWT)

时间:2020-06-15 18:11:37      阅读:49      评论:0      收藏:0      [点我收藏+]

标签:long   void   pre   for   传送门   cti   return   math   ++   

题目

传送门

思路

因为三个候选人实际上是一样的

所以我们只需要求出一个人的答案乘以\(3\)就行了

我们考虑A与B的比赛,和A与C的比赛

我们定义\(1\)为这个人在比赛中选了\(A\)

我们考虑每一个人的所有状态

\((0,0)\Rightarrow CBA,BCA\\(0,1)\Rightarrow BAC\\(1,0)\Rightarrow CAB\\(1,1)\Rightarrow ABC,ACB\)

对于\(f(x)\)的这个函数,实际上\(x\)为一种方案

也就是在A和B中,以及A和C中,\(f(x)\)均为1

之后我们考虑怎么求方案

我们定义\(g(x)=f(x)*f(x)\)

此时的乘法为按\(xor\)卷起来

对于一种下标,我们考虑有多少种可以构建出这个方案,

对于下标\(i\),我们定义\(i\)在二进制下0的个数为\(cnt\),方案即为\(2^{cnt}*1^{n-cnt}=2^{cnt}\)

\(ans=\sum_{i=0}^{(1<<n)-1}2^{cnt}*g_i\)

代码

#include<iostream>
using namespace std;
const int mod=1e9+7;
const int inv=(mod+1)/2;
namespace dwt
{
	void dwtxor(int l,int r,long long *a)
	{
		if(l==r)
			return;
		int mid=(l+r)>>1;
		long long t1,t2;
		for(int i=l;i<=mid;i++)
		{
			t1=a[i];
			t2=a[i-l+1+mid];
			a[i]=(t1+t2)%mod;
			a[i-l+1+mid]=(t1-t2+mod)%mod;
		}
		dwtxor(l,mid,a);
		dwtxor(mid+1,r,a);
	}
	void idwtxor(int l,int r,long long *a)
	{
		if(l==r)
			return;
		int mid=(l+r)>>1;
		idwtxor(l,mid,a);
		idwtxor(mid+1,r,a);
		long long t1,t2;
		for(int i=l;i<=mid;i++)
		{
			t1=a[i];
			t2=a[i-l+1+mid];
			a[i]=(t1+t2)*inv%mod;
			a[i-l+1+mid]=(t1-t2+mod)*inv%mod;
		}
	}
}
using namespace dwt;
int n,len;
long long a[(1<<21)+1];
long long ans;
string s;
int fj(int x)
{
	int ret=0;
	while(x)
	{
		if(x&1)
			ret++;
		x>>=1;
	}
	return 1<<(n-ret);
}
int main()
{
	cin>>n;
	cin>>s;
	for(int i=0;i<s.length();i++)
		a[i]=s[i]-‘0‘;
	dwtxor(0,(1<<n)-1,a);
	for(int i=0;i<(1<<n);i++)
		a[i]=a[i]*a[i]%mod;
	idwtxor(0,(1<<n)-1,a);
	for(int i=0;i<(1<<n);i++)
		ans=(ans+(a[i]*fj(i))%mod)%mod;
	cout<<ans*3%mod;
	return 0;	
}

习题:Random Elections (DWT)

标签:long   void   pre   for   传送门   cti   return   math   ++   

原文地址:https://www.cnblogs.com/loney-s/p/13131966.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!