[zroj 51] [Pendulum] : 線性篩
阿新 • • 發佈:2017-08-09
ntp 一次 兩個 style size cstring cst 更遠 世界
問題描述
Evan 站在巨大的世紀鐘擺前,觀察著鐘擺上方數字的塌縮。他發現,鐘擺每擺動?次,上方的數字就會變成把它分解質因數後每一項的和。例如 12 =2 × 2 × 3,那麽擺動一次後數字變成 2 + 2 + 3 = 7。現在,上方的數字正好是 x。Evan 還有 y 秒就要去新世界探索了,他想知道在鐘擺擺動 y 次到他離開時,上方的數字是多少。
輸入格式
第一行一個整數n,表示詢問個數。後面n行每行兩個整數x和y。
輸出格式
n行,每行一個答案表示離開時上方的數字。
樣例輸入
2
5 3
20 1
樣例輸出
5
9
數據範圍
n<=3*10^5,x<=10^7,y<=10^9
一些想法
一句話題意:給定x和y,每次將x質因數分解後的每一項求和作為新的x,問y次後的x。
暴力的搞一下10^7以內的所有數進行的變換,發現每個數的變換次數都不超過20次就會變成質數,而我們發現一旦變為了素數或者是4,無論再變換多少次都是不再變的。於是我們使用線性篩,開一個f數組,f[i]表示i質因數分解後的每一項的和。根據分析很明顯的知道當i為素數時f[i]=i,當為一個合數為prime[j]*i時f[prime[j]*i]=f[i]+prime[j]。所以最終我們只需要在歐拉篩中插入兩句話。
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<queue> using namespace std; #define debug(x) cerr<<#x<<‘=‘<<x<<endl #define MAXN 10000001 #define NUM 669999 int prime[NUM]; bool flag[MAXN]; int x,y,n; int f[MAXN]; int Euler(int n){ int cntprime=0; memset(flag,false,sizeof(flag)); memset(f,0,sizeof(f)); for (int i = 2; i <= n; i++) { if (!flag[i]) { f[i]=i; //第一句 prime[++cntprime] = i; } for (int j = 1; j <= cntprime && prime[j]*i <= n; j++) { f[prime[j]*i]=f[i]+prime[j]; flag[i*prime[j]] = true;// 第二句 if (i % prime[j] == 0) break; } } } int work(int x,int y){ while (y){ if (x==f[x]) {//分解為素數時不會再變化 ans=x; break; } else ans=x=f[x]; y--; } return ans; } int main (){ Euler(MAXN); cin>>n; for (int i=1;i<=n;i++){ scanf("%d%d",&x,&y); printf("%d\n",work(x,y)); } return 0; }
九月
目擊眾神死亡的草原上野花一片
遠在遠方的風比遠方更遠
我的琴聲嗚咽 淚水全無
我把這遠方的遠歸還草原
一個叫木頭 一個叫馬尾
我的琴聲嗚咽 淚水全無
遠方只有在死亡中凝聚野花一片
明月如鏡高懸草原映照千年歲月
我的琴聲嗚咽 淚水全無
只身打馬過草原
Sylvia
二零一七年八月九日
[zroj 51] [Pendulum] : 線性篩