K尾相等数
时间限制:3000 ms | 内存限制:65535 KB
难度:1
- 描述
- 输入一个自然数K(K>1),如果存在自然数M和N(M>N),使得K^M和K^N均大于等于1000,且他们的末尾三位数相等,则称M和N是一对“K尾相等数”。下面请编程求出M+N最小的K尾相等数。
- 输入
- 第一行包含一个正整数T,T<10000,表示有T组数据;
随后有N行,每行包括一个整数K(K<2*10^10); - 输出
- 对于输入的每个整数K,输出对应的M+N的最小值;
- 样例输入
-
1 2
- 样例输出
-
120
-
测试数据: -
25
125
1000
1234
111111
1000003
123454321
测试数据结果:
7
6
3
56
52
102
27
-
分析:
1.上面的要点中,1,2,3,5,6都是辅助条件,关键是弄清楚第4点。末尾三位相等是什么意思?比如 123456 末尾三位是 ‘456’ 而 45678 末尾三位则是‘678’。显然(虽然我也不喜欢在书上看到这个字眼,但是这里确实是很显然……),这里指的是10进制数的末尾3位,如何取末尾3位的数字?很显然( =.=! )将这个数字对1000求模就可以了。
2.仔细思考后,我们可以注意到,任何数对1000求模只有1000种可能(0~999),所以我们将K^Power 中的Power从1(为什么不是0?因为K^0=1<1000,而我们不考虑小于1000的情况,题解第3点)到1001逐个求值,总有相等的两个数字。因为结果只有1000种可能,但是有1001次求值,哪怕前1000次所求结果都不一样,最后一次的值必然与前面1000种其中的一种相等(相关知识:抽屉原理1)。
-
代码:
-
1 #include <iostream> 2 #include <memory> 3 #include<cstring> 4 5 using namespace std; 6 7 int Record[1000]; // 用以记录的一维数组 8 9 int KTail( int K ) 10 { 11 memset( Record, 0, sizeof(Record) ); 12 int Product = 1; 13 bool bTakeRecord = false; // 需要一个标记,用以判断是否>=1000 14 if ( K>=1000 ) 15 { 16 bTakeRecord = true; 17 K=K%1000; 18 } 19 20 for ( int Power = 1; Power<=1001; ++ Power) 21 22 { 23 Product *= K; // Product = (K^Power-1)%1000 * K 24 if ( bTakeRecord || Product>=1000 ) // 必须符合题目的条件 K^Power>=1000 25 { 26 bTakeRecord = true; // 考虑到有可能之前是false,再赋值 27 Product = Product%1000; 28 29 if ( Record[Product]==0 ) 30 31 Record[Product] = Power; 32 33 else 34 return Power + Record[Product]; 35 36 } 37 } 38 39 return -1; // 这行其实可以不写,因为不可能到这里,但是为了不让编译器提示编译警告 40 // 信息,还是加上吧。 41 } 42 43 int main() 44 { 45 int t,k; 46 cin>>t; 47 while(t--) 48 49 { 50 cin>>k; 51 cout<<KTail(k)<<endl; // 输出结果 52 } 53 54 return 0; 55 }
-