牛客練習賽29-F:算式子
阿新 • • 發佈:2019-02-12
時間限制:C/C++ 2秒,其他語言4秒
空間限制:C/C++ 262144K,其他語言524288K
64bit IO Format: %lld
題目描述
給定 個整數 。保證 。
對於每個,求出 。為了避免過量輸出,你只需要將所有的 m 個結果異或起來輸出。
輸入描述:
第一行兩個整數n,m。
第二行n個整數,第i個表示。
輸出描述:
一行一個整數,表示所有結果異或起來的結果。
示例1
輸入
2 2
1 2
輸出
0
示例2
輸入
10 10
1 3 5 5 2 5 9 3 1 10
輸出
60
備註: ,
思路:對於,列舉分母x以及x的倍數,其中位於裡的數除以x的值都是k,所以可以統計的值在這個區間裡的個數,然後加入到x的答案裡。
對於,同理,列舉分母及其倍數,其中位於區間裡的x的答案都會加上的值在這個區間裡的個數*k。
複雜度=
#include<bits/stdc++.h>
using namespace std;
const int MAX=4e6+10;
typedef long long ll;
ll ans[MAX];
int a[MAX],cnt[MAX];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
cnt[a[i]]++;
}
for(int i=1;i<=m;i++)
{
for(int j=i;j<=m;j+=i)
{
ans[j]+=1ll*j/i*cnt[i];
ans[j+i]-=1ll*j/i*cnt[i];
}
}
for(int i=1;i<=m;i++)ans[i]+=ans[i-1];
for(int i=1;i<=2*m;i++)cnt[i]+=cnt[i-1];
for(int i=1;i<=m;i++)
{
for(int j=i;j<=m;j+=i)ans[i]+=1ll*j/i*(cnt[j+i-1]-cnt[j-1]);
}
ll sum=0;
for(int i=1;i<=m;i++)sum^=ans[i];
cout<<sum<<endl;
return 0;
}