1. 程式人生 > >洛谷十月月賽2T1瀏覽器P4932

洛谷十月月賽2T1瀏覽器P4932

傳送門

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;
}