UOJ #548. 数学
作者:互联网
【题目描述】:
JATC的数学老师总是给课堂一些有趣的数学问题,这样他们就不会觉得无聊。今天问题如下。给定一个整数n,您可以零次或多次执行以下操作:
1、 MUL X:替换n为n乘以X (X是一个任意的正整数)。
2、 sqrt:替换n为sqrt(n)(要应用此操作,sqrt(n)必须是整数)。
你可以多次使用这些操作,使得n变为最小,并找到使n变为最小的最少操作次数。
显然,班上没有人知道这个问题的答案,也许你可以帮助他们?
【输入描述】:
输入一个整数n(1≤n≤10^15)初始数字。
【输出描述】:
输出两个整数,第一个为n能够变成的最小值,第二个为最少操作次数。
【样例输入1】:
20
【样例输出1】:
10 2
【样例输入2】:
5184
【样例输出2】:
6 4
【样例说明】:
在第一个示例中,可以应用mul 5操作得到 100,然后sqrt得到10。
在第二个示例中,可以先应用sqrt来获取72,然后MUL 18 得到 1296最后两个sqrt,你得到6。
注意,即使初始值n少于或等于 10^6,但在应用一个或多个操作之后,它仍然可能变得超过10^6。
【时间限制、数据范围及描述】:
时间:1s 空间:256M
30%的数据:最多只是用其中一个操作;
60%的数据:1≤n≤10^6
100%的数据:1≤n≤10^15
代码:
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=10000000; bool u[N+10]; int su[5000000], num; void prepare() { int i,j; memset(u,true, sizeof(u)); for(i=2; i<=10000000; i++) { if(u[i]) su[++num]=i; for(j=1; j<=num; j++) { if(i*su[j]>N) break; u[i*su[j]]=false; if(i%su[j]==0) break; } } } int main() { prepare(); int n,i,j,k; while(scanf("%d",&n)!=EOF&&n>0) { if(n<8) { puts("NO"); continue; } if(u[n-6]) printf("2 2 2 %d\n",n-6); else if(u[n-7]) printf("2 2 3 %d\n",n-7); else if(u[n-8]) printf("2 3 3 %d\n",n-8); else { if(n%2==0) { printf("2 2 "); n-=4; } else { printf("2 3 "); n-=5; } for(i=1; i<=num; i++) { if(su[i]*2>n) break; if(u[n-su[i]]) { printf("%d %d\n",su[i],n-su[i]); break; } } } } return 0; }
标签:10,int,样例,su,数学,sqrt,UOJ,548,include 来源: https://www.cnblogs.com/mysh/p/11351244.html