原题及翻译
For a positive integer N , the digit-sum of N is defined as the sum of N itself and its digits.
对于正整数n,n的位数和定义为n本身及其位数的和。
When M is the digitsum of N , we call N a generator of M .
当M是n的位数,我们称n为m的生成器。
For example, the digit-sum of 245 is 256 (= 245 + 2 + 4 + 5).
例如,245的数字和为256(=245+2+4+5)。
Therefore, 245 is a generator of256.
因此,245是256的生成器。
Not surprisingly, some numbers do not have any generators and some numbers have more than one generator.
不足为奇,有些数字没有任何生成器,有些数字有多个生成器。
For example, the generators of 216 are 198 and 207.
例如,216的生成器是198和207。
You are to write a program to find the smallest generator of the given integer.
您要编写一个程序来查找给定整数的最小生成器。
Input
输入
Your program is to read from standard input.
您的程序将从标准输入中读取。
The input consists of T test cases.
输入由T测试用例组成。
The number of test cases T is given in the first line of the input.
测试用例数t在输入的第一行给出。
Each test case takes one line containing an integer N , 1 ≤ N ≤ 100, 000.
每个测试用例取一行,包含一个整数n,1≤n≤100000。
Output
输出
Your program is to write to standard output.
您的程序将写入标准输出。
Print exactly one line for each test case.
每个测试用例只打印一行。
The line is to contain a generator of N for each test case.
对于每个测试用例,该行包含一个n的生成器。
If N has multiple generators, print the smallest.
如果n有多个生成器,请打印最小的。
If N does not have any generators, print ‘0’.
如果n没有任何生成器,请打印“0”。
Sample Input
3
216
121
2005
Sample Output
198
0
1979
思路
1.第一个想到的就是,暴力枚举,一开始写的是六层循环,作死的节奏,结果肯定是超时的,然后再把循环层数减到两层,从1枚举到最大值,但是每次枚举都要与n个数判断是否符合条件,时间复杂度O(n2),还是会超时,只有把时间复杂度降到O(n),才能AC。
2.枚举也有两种方法,第一种就是将1~ max枚举然后分别判断,第二种是将1~ 100000的所有生成元与其数字对应,没有生成元的就标为0,然后分别输入数字将其对应的生成元输出。
代码分析
先把超时的代码放出来,算法很简单,很好理解,但是,超时,不管怎样,没AC就是WA。
#include <stdio.h>
#include <string.h>
int main ()
{
int n,max=0;
scanf("%d",&n);
int m[n];
for(int i=0;i<n;i++)
{
scanf("%d",&m[i]);
if(m[i]>max) max=m[i];
}
int x[n],flag[n],index=0;
memset(x,0,sizeof(x));
memset(flag,0,sizeof(flag));
for(int i=1;i<=max;i++)
{
int a=i/100000%10,b=i/10000%10,c=i/1000%10,d=i/100%10,e=i/10%10,f=i/1%10;
for(int j=index;j<n;j++)
{
if(a*100000+b*10000+c*1000+d*100+e*10+f+a+b+c+d+e+f==m[j])
{
x[j]=a*100000+b*10000+c*1000+d*100+e*10+f;flag[j]=1;index++;
}
}
}
for(int i=0;i<n;i++)
{
if(flag[i]==0) printf("0 \n");
else printf("%d \n",x[i]);
}
return 0;
}
接下来看正确的结果:
1.创建一个全局变量的数组将从1~100000的所有生成元存储起来:
#define max 100000
int ans[max];
2.计算生成元并存储:
for(int m=1;m<max;m++)
{//从1开始遍历
int x=m,y=m;
//x,y作为计算生成元的中间变量
while(x>0)
{//将y分别与x的每一位相加,即生成元
y+=x%10;
x/=10;
}
if(ans[y]==0||ans[y]>m) ans[y]=m;
//将即将输入的数字y与其生成元m对应
}
完整代码
#include <stdio.h>
#include <string.h>
#define max 100000
int ans[max];
int main()
{
int t,n;
memset(ans,0,sizeof(ans));
for(int m=1;m<max;m++)
{
int x=m,y=m;
while(x>0)
{
y+=x%10;
x/=10;
}
if(ans[y]==0||ans[y]>m) ans[y]=m;
}
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
printf("%d\n",ans[n]);
}
return 0;
}