Dirichlet前缀和
题目描述
输入格式
为了避免过大的输入,本体的输入使用随机数生成器。
输入中只有一行两个整数n,s。其中s为32位无符号整数,用来生成数据。
接下来,你要调用n次随机数生成器,分别生成
a
1
a_1
a1~
a
n
a_n
an。
输出格式
为了避免过大的输出,你只需要输出一个32位无符号整数,表示所有 b i b_i bi的异或和。
输入样例
5 1477
输出样例
2608816472
说明/提示
样例中
数列 a 为 397153977, 974453892, 352446086, 334987182, 2086335567。
数列b为397153977,1371607869,749600063,1706595051,2483489544。
解题思路
首先我们要将所有的质数筛选出来,可是数据太大,用普通的容易超时,所以我们就要考虑使用欧拉筛。
将所有的质数筛出来后,我们在求出每个数的约数,然后将有贡献的挑选出来。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define uint unsigned int
using namespace std;
uint s,n,number,p[20000010],a[20000010],veed[20000010],cont;
inline uint getnext()//随机数生成器
{
s^=s<<13;
s^=s>>17;
s^=s<<5;
return s;
}
void olash()//欧拉筛
{
for(uint i=2; i<=n; i++)
{
if(!veed[i])
p[++cont]=i;
for(uint j=1; i*p[j]<=n&&j<=cont; j++)
{
veed[i*p[j]]=1;
if(i%p[j]==0)
break;
}
}
}
int main()
{
uint i,j;
cin>>n>>s;
for(i=1;i<=n;i++)
a[i]=getnext();
olash();
for(i=1;i<=cont;i++)
for(j=1;j*p[i]<=n;j++)
a[j*p[i]]+=a[j];
for(i=1;i<=n;i++)
number^=a[i];//求异或和
cout<<number;
return 0;
}