SDUT 2022 Spring Individual Contest(for 21) - 5 - Virtual Judge
通常来说,题面短的题目一般都比较难,所以我要把题面写得很长很长。
通常来说,题面短的题目一般都比较难,所以我要把题面写得很长很长。
通常来说,题面短的题目一般都比较难,所以我要把题面写得很长很长。
鸽子数字由以下过程定义:从任何正整数开始,将数字替换为其各个数位的平方和,并重复该过程,直到该数字等于1。如果不能,则这个数字不是鸽子数。
例如7是鸽子数,因为7->49->97->130->10->1。(7*7=49,4*4+9*9=97,9*9+7*7=130....如此类推)
显然1是第一个鸽子数。
有Q个询问,每个询问给出一个数k,你需要输出第k个鸽子数。
Input
第一行一个Q,代表询问的个数(Q<=100000)
接下来Q行,每行一个数字k(k<150000)
Output
每行输出一个数,代表第k个鸽子数
Sample
Inputcopy | Outputcopy |
---|---|
2 1 2 | 1 7 |
思路一:打表
我们用两个数组sum和vis,一个开150005,一个1005,先算前一千个数,标记是否为鸽子数,然后再while循环,找到150000个数即可,虽然是暴力但是时间完全够了93ms。
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
int sum[150005];
int vis[1005];
int main()
{
int n,m,num;
int k=1,i=2;
vis[1]=1;
sum[k]=1;
while(i<=1000)
{
n=i;
while(n!=1&&n!=4)
{
num=0;
while(n)
{
num+=((n%10)*(n%10));
n/=10;
}
n=num;
}
if(n==1)
{
vis[i]=1;
sum[++k]=i;
}
i++;
}
while(k<=150000)
{
num=0;
n=i;
while(n)
{
num+=((n%10)*(n%10));
n/=10;
}
if(vis[num])sum[++k]=i;
i++;
}
scanf("%d",&n);
while(n--)
{
scanf("%d",&m);
printf("%d\n",sum[m]);
}
}
思路二:暴力
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define read(x) scanf("%d", &x)
#define fori(a,b) for(int i=a; i<=b; i++)
using namespace std;
typedef long long LL;
int main()
{
int a[150010],T,n,sum,cnt=0;
a[++cnt] = 1;
fori(2, 1050000)
{
n=i;
while(n!=1 && n!=4)
{
sum=0;
while(n)
{
sum += (n%10)*(n%10);
n /= 10;
}
n = sum;
}
if(n == 1)
a[++cnt] = i;
if(cnt == 150000)
break;
}
read(T);
while(T--)
{
read(n);
printf("%d\n",a[n]);
}
return 0;
}