习题:Random Elections (DWT)

Posted loney-s

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了习题:Random Elections (DWT)相关的知识,希望对你有一定的参考价值。

题目

传送门

思路

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

所以我们只需要求出一个人的答案乘以(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)的主要内容,如果未能解决你的问题,请参考以下文章

CF850E Random Elections

字符串练习题

Codeforces 458C - Elections

CodeForces 458C Elections

CodeForces - 1593A Elections

CodeForces - 1593A Elections