终于遇到了数论题
题目不难但是略微复杂
A(K位)是Forever number当且仅当
- A每一位的数值之和为m
- A+1每一位的数值之和为n
- m和n的最大公约数是大于2的素数
dfs枚举A的每一位,通过m(A每一位的数值之和)剪枝
需要注意,在输出时需要按照n排序,若n相等则按照A排序
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
int k, m;
int a[15];
int flag = 0;
struct node {
int n;
LL A;
};
node ans[1000];
int cnt;
int cmp(node &X,node &Y) {
if (X.n != Y.n) return X.n < Y.n;
else return X.A < Y.A;
}
int gcd(int n, int m) {
int r = n % m;
while (r) {
n = m;
m = r;
r = n % m;
}
return m;
}
void check() {
LL num1 = 0;
for (int i = 1; i <= k; ++i)
num1 = num1 * 10 + (LL)a[i];
LL num2 = num1 + 1;
int n = 0;
while (num2) {
n += int(num2 % 10);
num2 /= 10;
}
int c = gcd(n, m);
if (c <= 2) return;
for (int i = 2; i <= (int)sqrt((double)c); ++i)
if (c % i == 0) return;
cnt++;
ans[cnt].n = n;
ans[cnt].A = num1;
}
void dfs(int t, int res) {
if (t > k) {
if (res == 0) check();
return;
}
int s = 0;
if (t == 1) s = 1;
for (int i = s; i <= min(9,res); ++i) {
a[t] = i;
dfs(t + 1, res - i);
a[t] = 0;
}
}
int main()
{
int T;
scanf("%d",&T);
for (int i = 1; i <= T; ++i) {
scanf("%d%d", &k, &m);
cnt = 0;
printf("Case %d\n",i);
dfs(1, m);
if (!cnt) printf("No Solution\n");
else {
sort(ans + 1, ans + 1 + cnt, cmp);
for (int j = 1; j <= cnt; ++j)
printf("%d %lld\n", ans[j].n, ans[j].A);
}
}
return 0;
}