1. 程式人生 > >[zroj 51] [Pendulum] : 線性篩

[zroj 51] [Pendulum] : 線性篩

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] : 線性篩