PAT-2019年秋季考试-甲级 7-1 Forever (20 分)

7-1 Forever (20 分)
“Forever number” is a positive integer A with K digits, satisfying the following constrains:

  • the sum of all the digits of A is m;
  • the sum of all the digits of A+1 is n; and
  • the greatest common divisor of m and n is a prime number which is greater than 2.

Now you are supposed to find these forever numbers.

Input Specification:

Each input file contains one test case. For each test case, the first line contains a positive integer N (≤5). Then N lines follow, each gives a pair of K (3) and m (1), of which the meanings are given in the problem description.

Output Specification:

For each pair of K and m, first print in a line Case X, where X is the case index (starts from 1). Then print n and A in the following line. The numbers must be separated by a space. If the solution is not unique, output in the ascending order of n. If still not unique, output in the ascending order of A. If there is no solution, output No Solution.

Sample Input:

2
6 45
7 80

Sample Output:

Case 1
10 189999
10 279999
10 369999
10 459999
10 549999
10 639999
10 729999
10 819999
10 909999
Case 2
No Solution

题意
给你位数K,各位数字之和m。请你计算K位数中所有满足:1.该数字各个位的数字之和为m,2.该数字加一之后各个位数字之和n,n和m的最小公倍数必须是比2大的质数。

思路
暴力法正常就是罗列所有k位数,对每个数进行判断。跟去年狼人杀一样,题目描述的比较复杂(可能是我英语比较辣鸡)。一开始我暴力法能得到三个点的分最后一个过不了。
那接下来就是要缩小步进或者剪枝,我当时是没想出来,但是出来后听到一个大佬分析,他把步进从1优化成10。举个栗子,假设K是4,那么暴力法就要从1000一直循环到9999.但是实际上当个位数位9了以后,即1009(假设1009不满足m),则继续加一变成1010,但是大佬从个位为9开始后将步进设置为10,即1010和1019的各个位数之和是一致的,这样就能减小时间复杂度。

我在想怎么优化的时候想了另一个办法,用递归。K个位数,除了最高位是1-9,剩余各个位都是0-9.那么我从最高位往最低递归放置1(0)-9后计算是否满足。
我是这么优化递归的,在进入递归后,判断当前位数和是否大于m或者当前位数和在剩下位数即使都是9的情况下也不能满足总和大于等于m那么退出本层递归。
第一个很好理解,m=5,k=6的话,放了一位9???,即使剩下位数全是0也不满足,排除;
第二个,假如k=5,m=45,放了一位1???,那么剩下四位全是9,总和也才37,排除。

#include 
#include 
#include 
#include 
#include 
#define maxsize 10000
using namespace std;
int n, k, m, N, now = 0;
struct Node
{
    int n, v;
};
vector out;
deque dig;
int gcb(int a, int b)
{
    if (b > a)
        swap(a, b);
    if (a % b == 0)
        return b;
    else
    {
        int c = a % b;
        a = b;
        b = c;
        return gcb(a, b);
    }
}
bool isPrime(int a)
{
    if (a <= 2)
        return false;
    for (int i = 2; i <= sqrt(1.0 * a); i++)
        if (a % i == 0)
            return false;
    return true;
}
int getTotal(int tmp)
{
    int sum = 0;
    while (tmp > 0)
    {
        sum += tmp % 10;
        tmp /= 10;
    }
    return sum;
}
int caculate()
{
    deque t = dig;
    int result = 0, index = 0;
    while (!t.empty())
    {
        result = result + pow(double(10), index) * t.back();
        t.pop_back();
        index++;
    }
    return result;
}
void dfs(int digital, int sum, int index)
{
    if (sum > m || (sum + (digital)*9) < m)
        return;
    if (digital == 1)
    {
        for (int i = 0; i <= 9; i++)
        {
            sum += i;
            dig.push_back(i);
            if (sum == m)
            {
                now = caculate();
                int tmp = getTotal(now + 1);
                if (isPrime(gcb(tmp, m)))
                {
                    Node t;
                    t.v = now;
                    t.n = tmp;
                    out.push_back(t);
                }
                dig.pop_back();
                sum -= i;
                break;
            }
            dig.pop_back();
            sum -= i;
        }
    }
    else
    {
        int i = k == digital ? 1 : 0;
        for (; i <= 9; i++)
        {
            sum += i;
            dig.push_back(i);
            dfs(digital - 1, sum, index + 1);
            dig.pop_back();
            sum -= i;
        }
    }
}

bool cmp(Node a, Node b)
{
    return a.n != b.n ? (a.n < b.n) : a.v < b.v;
}
int main()
{
    std::iostream::sync_with_stdio(false);
    std::cin.tie(0);
    int totalm = 0;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> k >> m;
        out.clear();
        dfs(k, 0, 0);
        cout << "Case " << (i + 1) << endl;
        sort(out.begin(), out.end(), cmp);
        for (int j = 0; j < out.size(); j++)
            cout << out[j].n << " " << out[j].v << endl;
        if (out.size() == 0)
            cout << "No Solution" << endl;
    }
    return 0;
}

PAT-2019年秋季考试-甲级 7-1 Forever (20 分)_第1张图片

你可能感兴趣的:(pat)