ZOJ-3327-Friend Number【7th浙江省赛】【模拟】【数学】

56 篇文章 0 订阅
23 篇文章 0 订阅

ZOJ-3327-Friend Number


                    Time Limit: 1 Second      Memory Limit: 32768 KB

Given a positive integer x, let P(x) denotes the product of all x’s digits. Two integers x and y are friend numbers if P(x) = P(y). Here comes the problem: Given a positive integer x, of course it has a lot of friend numbers, find the smallest one which is greater than x.

Input

There are multiple test cases. The first line of input is an integer T (0 < T < 230) indicating the number of test cases. Then T test cases follow. Each case is an integer x (0 < x <= 101000). You may assume that x has no leading zero.

Output

For each test case, output the result integer in a single line. You should not output a number with leading zero.

Sample Input
3
12
19
222

Sample Output
21
33
241

题目链接:ZOJ-3327

题目大意:找到一个最小的数满足,P(x) = P(y)。P(x) 表示 x个数位的乘积

题目思路:分三种情况讨论
1. 如果只有个位一个0,就从十位上往高位找,找不是9的,找到加1,结束。找的过程遇到9,都改为0。如果都是9,就在数字最左边加一个1。
2. 如果有0,且不是上诉情况,那就直接从个位往高位走,遇到9,变0;遇到非9 ,加1,结束。
3. 如果没有0的话,把从个位开始,素数分解,并记录所有的素数。分解完一位,就判断下分解出来的素数能不能组成比 这一位大的 个位数,能的话取最小的这个数,设这个位为id。如123 ,个位分解完,得素数3,十位分解完得素数2,这个时候可以用分解的素数有2,3,2*3=6,要比2大且最小,所以选3。 所以十位改为3,素数3的个数减1。 接下来从个位,不停地放 已经得到的素数能组成最大的数,直到id的后一位为止。

如果一直没找到id位,就直接在原来的数前面加个‘1’ 输出即可。

参考博客:here

以下是代码:

#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <string>
#include <cstring>
using namespace std;

int pri[15] = {0};
string s;

void getprime(int n)
{
    if (n == 9) pri[3] += 2;
    if (n == 8) pri[2] += 3;
    if (n == 7) pri[7] ++;
    if (n == 6) pri[2]++,pri[3]++;
    if (n == 5) pri[5] ++;
    if (n == 4) pri[2] += 2;
    if (n == 3) pri[3] ++;
    if (n == 2) pri[2] ++;
    if (n == 1) pri[1] ++;
}

int usual(int n)
{
    if (n == 9 && pri[3] >= 2)
    {
        pri[3] -= 2;
        return 1;
    }
    if (n == 8 && pri[2] >= 3)
    {
        pri[2] -= 3;
        return 1;
    }
    if (n == 7 && pri[7] >= 1)
    {
        pri[7]--;
        return 1;
    }
    if (n == 6 && pri[2] >= 1 && pri[3] >= 1)
    {
        pri[2]--;
        pri[3]--;
        return 1;
    }
    if (n == 5 && pri[5] >= 1)
    {
        pri[5]--;
        return 1;
    }
    if (n == 4 && pri[2] >= 2)
    {
        pri[2] -= 2;
        return 1;
    }
    if (n == 3 && pri[3] >= 1)
    {
        pri[3]--;
        return 1;
    }
    if (n == 2 && pri[2] >= 1)
    {
        pri[2]--;
        return 1;
    }
    if (n == 1) return 1;

    return 0;
}

int sol()
{
    if (pri[3] >= 2)
    {
        pri[3] -= 2;
        return 9;
    }
    if (pri[2] >= 3)
    {
        pri[2] -= 3;
        return 8;
    }
    if (pri[7] >= 1)
    {
        pri[7] --;
        return 7;
    }
    if (pri[2] >= 1 && pri[3] >= 1)
    {
        pri[2] --, pri[3] --;
        return 6;
    }
    if (pri[5] >= 1)
    {
        pri[5] --;
        return 5;
    }
    if (pri[2] >= 2)
    {
        pri[2] -= 2;
        return 4;
    }
    if (pri[3] >= 1)
    {
        pri[3] --;
        return 3;
    }
    if (pri[2] >= 1)
    {
        pri[2] --;
        return 2;
    }

    return 1;
}

string solve(string s)
{
    int i,j;
    int flag = 0;
    int len = s.size();
    memset(pri,0,sizeof(pri));
    for (i = len - 1; i >= 0; i--)
    {
        getprime(s[i] - '0');
        int ok = 0;
        for (j = s[i] - '0' + 1; j <= 9; j++)
        {
            if (usual(j))
            {
                ok = 1;
                break;
            }
        }
        if (ok)
        {
            flag = 1;
            s[i] = j + '0';
            break;
        }   
    }
    if (flag)
    {
        int ii = i;
        for(int i = len - 1; i > ii; i--)
        {
            s[i] = sol() + '0';
        } 
    }
    else
    {
        cout << 1;
        for (int i = 0; i < s.size(); i++)
        {
            s[i] = sol() + '0';
        }
    }
    return s;
}

int find_zero(string s)
{
    int num = 0;
    for (int i = 0; i < s.size(); i++)
    {
        if (s[i] == '0')
        {
            num++;
        }
    }
    return num;
}

int main(){
    int t;
    cin >> t;
    while(t--)
    {
        cin >> s;
        int len = s.size();
        int zero = find_zero(s);
        if (s.size() == 1)
        {
            cout << 1 << s[s.size() - 1] << endl;
            continue;
        }
        else if (!find_zero(s))
        {
            string ans = solve(s);
            cout << ans << endl;
        }
        else
        {
            if (zero == 1 && s[s.size() - 1] == '0')
            {
                int cnt_9 = 0;
                for (int i = len - 2; i >= 0; i--)
                {
                    if (s[i] == '9')
                    {
                        s[i] = '0';
                        cnt_9++;
                    }
                    else
                    {
                        s[i]++;
                        break;
                    }
                }
                if (cnt_9 == len - 1)
                {
                    cout << 1;
                }
            }
            else
            {
                for (int i = len - 1; i >= 0; i--)
                {
                    if (s[i] != '9')
                    {
                        s[i]++;
                        break;
                    }
                    else s[i] = '0';
                }

            }
            cout << s << endl;
        }           
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值