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

牛客練習賽29 算式子

bsp algo style type contest -o const 時間 scan

鏈接:https://www.nowcoder.com/acm/contest/211/F
來源:牛客網

時間限制:C/C++ 2秒,其他語言4秒
空間限制:C/C++ 262144K,其他語言524288K
64bit IO Format: %lld

題目描述

給定 技術分享圖片 個整數 技術分享圖片 。保證 技術分享圖片 。 對於每個 技術分享圖片,求出 技術分享圖片。為了避免過量輸出,你只需要將所有的 m 個結果異或起來輸出。

輸入描述:

第一行兩個整數 技術分享圖片 。 第二行 技術分享圖片 個整數,第 技術分享圖片 個表示 技術分享圖片

輸出描述:

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

輸入

復制
2 2
1 2

輸出

復制
0

說明

技術分享圖片
 時,結果為 
技術分享圖片


技術分享圖片
時,結果為  
技術分享圖片


所以輸出
技術分享圖片
示例2

輸入

復制
10 10
1 3 5 5 2 5 9 3 1 10

輸出

復制
60

備註:

技術分享圖片 技術分享圖片 賽後看了很久旺神的代碼,終於看懂了這道題。 分析:首先我們需要處理兩種情況,x在上面和x在下面的情況 當x在上面時,我們需要記錄(1-m)的每個位置產生的貢獻,對於當前位置x的貢獻,等於它是多少個a[i]的倍數,我們可以將這個倍數關系,進行預處理的向上累加,如果:a[1]=1,a[2]=2,那麽我們用cnt[i]表示a數組中i的個數,那麽cnt[2]=1,cnt[1]=1,如果我們將倍數累加上去,cnt[2]=2,cnt[1]=1,也就是說在1這個位置產生的貢獻為1,在2這個位置產生的貢獻為2,當x=2時,我們累加1和2位置的貢獻即可,結果為3 ,那麽當x為k的時候,我們同樣累加1-k的貢獻即可,處理的時候可以用前綴和進行處理。 當x在下面的時候,我們需要找每個ai產生的貢獻,對於一個ai,它的貢獻可以這樣看,設定一個suma數組,讓1-ai的值為1,那麽當我們跑x的時候,累加上對應的suma[kx]的值即可,比如當前x的值為2,ai為8,那麽處理為讓suma的下標為1-8的位置+1, 當前貢獻等於suma[x]+suma[2x]+suma[3x]+suma[4x]. 這樣的話,我們就可以先跑所有的ai值,處理出最後的suma數組,然後在跑x,並不斷累加對應的suma[kx]的值 代碼如下:
#include <cstdio>
#include 
<cstring> #include <cmath> #include <algorithm> #include<vector> #include<set> #include<map> #include<queue> #include<stack> #include<iostream> using namespace std; typedef long long LL; const int MAXN=2e6+100; LL a[MAXN]; LL cnt[MAXN]; LL sumb[MAXN]; LL suma[MAXN]; LL n,m,x;
int main() { scanf("%lld%lld",&n,&m); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); suma[1]++; suma[a[i]+1]--; cnt[a[i]]++; } for(int i=1;i<=m;i++) suma[i]+=suma[i-1]; for(int i=m;i>=1;i--) { for(int k=i+i;k<=m;k+=i) cnt[k]+=cnt[i]; } for(int i=1;i<=m;i++) { sumb[i]=sumb[i-1]+cnt[i]; } LL up_x=0; LL down_x=0; LL ans=0; for(int i=1;i<=m;i++) { down_x=0; for(int j=i;j<=m;j+=i) down_x+=suma[j]; up_x=sumb[i]; ans^=(down_x+up_x); } printf("%lld\n",ans); return 0; }

牛客練習賽29 算式子