传送门
https://www.luogu.org/problemnew/show/P4932
题面
题目描述
__stdcall给了你n个点,第i个点有权值x[i],对于两个点u和v,如果x[u] xor x[v]的结果在二进制表示下有奇数个1,那么在u和v之间连接一个Edge,现在__stdcall想让你求出一共有多少个Edge。
如果你没能成功完成任务,那么__stdcall会让你痛苦一下,你这个测试点就没分了。
输入输出格式
输入格式:
一行六个整数,n,a,b,c,d,x[0]。
n是点的个数,每个点的权值需要用如下的方式生成。
你需要使用a,b,c,d和x[0]生成一个数组x,生成方式是这样的。
x[i]就是第i个点的权值,点的标号是1到n。
输出格式:
输出一个整数,表示一共有多少个Edge。**
思路
O(nlogn)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int read()
{
char ch=' ';
int f=1;int x=0;
while(ch<'0'||ch>'9')
{
if(ch=='-') f=-1;ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';ch=getchar();
}
return x*f;
}
const int N=1e7+100;
int x[N];
int n,a,b,c,d;
int calc(int x)
{
ll ret=0;
ll y=1ll*a*x%d*x%d;
ret+=y;
y=1ll*b*x%d;
ret=(ret+y)%d;
ret=(ret+c)%d;
return ret;
}
int cnt(int x)
{
int ret=0;
while(x)
{
if(x&1)
ret++;
x=x>>1;
}
return ret;
}
int main()
{
n=read();a=read();b=read();c=read();d=read();
x[0]=read();
int i,j;
for(i=1;i<=n;i++)
{
x[i]=calc(x[i-1]);
}
int odd=0,even=0;
for(i=1;i<=n;i++)
{
int popcnt=cnt(x[i]);
if(popcnt%2==1)
{
odd++;
}
else
{
even++;
}
}
printf("%lld\n",1ll*odd*even);
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int read()
{
char ch=' ';
int f=1;int x=0;
while(ch<'0'||ch>'9')
{
if(ch=='-') f=-1;ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';ch=getchar();
}
return x*f;
}
const int N=1e7+100;
int x[N];
int n,a,b,c,d;
int calc(int x)
{
ll ret=0;
ll y=1ll*a*x%d*x%d;
ret+=y;
y=1ll*b*x%d;
ret=(ret+y)%d;
ret=(ret+c)%d;
return ret;
}
int work(int x)
{
int ret=0;
while(x)
{
if(x&1)
ret++;
x=x>>1;
}
return ret;
}
const int M=1<<18;
int cnt[M+10];
void prework()
{
for(int i=0;i<M;i++)
{
cnt[i]=work(i);
}
}
int check(int x)
{
return cnt[x&(M-1)]+cnt[x>>18];
}
int main()
{
n=read();a=read();b=read();c=read();d=read();
x[0]=read();
int i,j;
for(i=1;i<=n;i++)
{
x[i]=calc(x[i-1]);
}
int odd=0,even=0;
prework();
for(i=1;i<=n;i++)
{
int popcnt=check(x[i]);
if(popcnt%2==1)
{
odd++;
}
else
{
even++;
}
}
printf("%lld\n",1ll*odd*even);
return 0;
}