问题描述
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
二零一七年八月九日
时间: 2024-11-06 07:51:29