1. 程式人生 > >牛客練習賽29: F. 算式子

牛客練習賽29: F. 算式子

題目描述

給定  個整數  。保證 

對於每個  ,求出 。為了避免過量輸出,你只需要將所有的 m 個結果異或起來輸出。

輸入描述:

第一行兩個整數  。

第二行  個整數,第  個表示  。

輸出描述:

一行一個整數,表示所有結果異或起來的結果。

輸入

2 2
1 2

輸出

0

思路:

算一下每個a[i]/x的貢獻和每個x/a[i]的貢獻

然後就是類似於質數篩的過程,對於每個i∈[1, m]暴力它所有的倍數

複雜度O(mlnm)

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
int sum[4005005];
LL ans[2005005], dx[4005005];
int main(void)
{
	LL now, bet;
	int n, m, i, x, j;
	scanf("%d%d", &n, &m);
	for(i=1;i<=n;i++)
	{
		scanf("%d", &x);
		sum[x]++;
	}
	for(i=1;i<=m*2;i++)
		sum[i] += sum[i-1];
	for(i=1;i<=m;i++)
	{
		for(j=1;j*i<=m;j++)
		{
			ans[i] += (LL)j*(sum[i*(j+1)-1]-sum[i*j-1]);
			dx[i*j] += (LL)j*(sum[i]-sum[i-1]);
			dx[i*(j+1)] -= (LL)j*(sum[i]-sum[i-1]);
		}
	}
	bet = now = 0;
	for(i=1;i<=m;i++)
	{
		now += dx[i];
		ans[i] += now;
		bet ^= ans[i];
	}
	printf("%lld\n", bet);
	return 0;
}