题目:
描述
H国的身份证号码是一个N位的正整数(首位不能是0)。此外,由于防伪需要,一个N位正整数是合法的身份证号码当且仅当每位数字都小于等于K,并且任意相邻两位数字的乘积也小于等于K。例如对于K=5, 101、211、210等都是合法的号码,而106、123、421等都是非法的号码。
给定一个正整数N以及K,请从小到大输出所有合法的号码。
输入 两个整数N和K。
对于80%的数据,1 ≤ N ≤ 6。
对于100%的数据,1 ≤ N ≤ 9,1 ≤ K ≤ 5。
输出 按从小到大的顺序输出所有合法的N位号码,每个号码占一行。
样例输入
2 4
样例输出
10
11
12
13
14
20
21
22
30
31
40
41
原题链接:https://hihocoder.com/problemset/problem/1558
很显然,这是一道水题,但是如果不优化一下的话会TLE的~
一开始的写法,也就是没优化之前如下,能通过90%,还有一个超时了:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<math.h>
using namespace std;
void isValid(int a,int n,int k){
int xx[10] = {0};
int t = n;
int p = a;
if(n == 1){
if(a <= k){
cout<<a<<endl;
}
return;
}
for(int i=0;i<n;i++){
xx[i] = p%10;
p /= 10;
if(xx[i] > k){
return;
}
}
xx[n] = xx[0];
for(int i=0;i<n-1;i++){
if(xx[i] * xx[i+1] > k){
return;
}
}
cout<<a<<endl;
}
int main(){
int n,k;
while(cin>>n>>k){
int minNum = pow(10,n-1);
int maxNum = pow(10,n-1)*(k+1)+0.5;
for(int i=minNum;i<maxNum;i++){
isValid(i,n,k);
}
}
return 0;
}
经过优化的代码如下,这个倒是AC了,优化思路也比较简单,比如k为5,那么当遍历到161的时候自动跳转到200,这样就省去很多次计算了:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<math.h>
using namespace std;
int main(){
int n,k;
while(cin>>n>>k){
int minNum = pow(10,n-1)+0.5;
int maxNum_1 = ((int)(pow(10,n-1)+0.5))*(k+1);
int maxNum_2 = pow(10,n)+0.5;
int maxNum = maxNum_1<maxNum_2?maxNum_1:maxNum_2;
for(int i=minNum;i<maxNum;i++){
int xx[10] = {0};
int t = n;
int p = i;
bool flag = false;
if(n == 1){
if(i <= k){
cout<<i<<endl;
}
continue;
}
for(int j=0;j<n;j++){
xx[j] = p%10;
p /= 10;
if(xx[j] > k){
if(j != 0){
int ttt = pow(10,1+j)+0.5;
i = ((i/ttt) * ttt+ttt);
i--;
}
flag = true;
break;
}
}
if(flag){
flag = false;
continue;
}
xx[n] = xx[0];
for(int j=0;j<n-1;j++){
if(xx[j] * xx[j+1] > k){
flag = true;
break;
}
}
if(flag){
flag = false;
continue;
}
cout<<i<<endl;
}
}
return 0;
}