题目传送门
终于遇到了数论题
题目不难但是略微复杂
A(K位)是Forever number当且仅当
- A每一位的数值之和为m
- A+1每一位的数值之和为n
- m和n的最大公约数是大于2的素数
dfs枚举A的每一位,通过m(A每一位的数值之和)剪枝
需要注意,在输出时需要按照n排序,若n相等则按照A排序
#include#include #include #include #include #include #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)ceil(sqrt(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 %dn",i); dfs(1, m); if (!cnt) printf("No Solutionn"); else { sort(ans + 1, ans + 1 + cnt, cmp); for (int j = 1; j <= cnt; ++j) printf("%d %lldn", ans[j].n, ans[j].A); } } return 0; }



