ZOJ 3327(思路题)

本文介绍了一种算法,用于解决给定一个大数后找到下一个更大的数,且这两个数的各位数字乘积相等的问题。通过统计2、3、5、7这四个质数的个数并尝试构造符合条件的大数来实现。
题解:
给定一个很大的数,求一个比其大,且各位上的数的积相等。

情况:

 如果数字当中有0,故单独判断,只要将其最后一位+1,但当有且仅有一个0且0在最后一位,我们得特殊处理,不然最后一位+1,把0给去掉了,故从倒数第二位开始。

其他情况,从低位向高位遍历,记录2,3,5,7的个数,对于每个位,看是否可以用已经有的2,3,5,7的个数构成大于此数的最小数,如果存在这个数字,那么可以停止遍历,此数高位的数保持不变,低位的数:从低位遍历,用已有的2,3,5,7构造尽量大的小于10的数;如果不存在这个数字,结果的最高位为1,然后从最低位遍历。



#include<cstdlib>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<list>
#include<queue>
#include<vector>
#define ULL unsigned long long
#define LL long long
#define UI unsigned int
#define inf 0x7fffffff
#define eps 1e-7
#define N 10100
using namespace std;
int n;
char str[N];
LL z[10];//保存大数
const int x[4]= {2,3,5,7};
void add(int n)
{
    for (int i=0; i<4&&n!=1; ++i )
    {
        while(n%x[i]==0)
        {
            z[x[i]]++;
            n/=x[i];
        }
    }
}
void jian(int n)
{
    for (int i=0; i<4&&n!=1; ++i )
    {
        while(n%x[i]==0)
        {
            z[x[i]]--;
            n/=x[i];
        }
    }
}
int ok(int n)
{
    if(n==1)return 1;
    for (int i=0; i<4&&n!=1; ++i )
    {
        int num=0;
        while(n%x[i]==0)
        {
            num++;
            n/=x[i];
        }
        if(num>z[x[i]])return 0;
    }
    return 1;
}
void fun(int k)
{
    for(int i=n-1;i>=k;i--)
    {
        for(int j=9;j>=1;j--)
        if(ok(j))
        {
            jian(j);
            str[i]=j+'0';break;
        }
    }
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("ex.in","r",stdin);
#endif
    int t;
    scanf("%d%*c",&t);
    while (t--)
    {
        scanf("%s",str);
        n=strlen(str);
        int num=0;
        for(int i=0; i<n; i++)
            if(str[i]=='0')
                num++;
        memset(z,0,sizeof(z));
        if(num==1&&str[n-1]=='0')
        {
            int flag=0;
            for(int i=n-2; i>=0; i--)
            {
                str[i]++;
                if(str[i]>'9')
                    str[i]='0';
                else
                {
                    flag=1;
                    break;
                }
            }
            if(!flag)
                printf("1");
        }
        else if(num>=1)
        {
            for(int i=n-1; i>=0; i--)
            {
                str[i]++;
                if(str[i]>'9')
                    str[i]='0';
                else
                {
                    break;
                }
            }
        }
        else
        {
            add(str[n-1]-'0');
            int flag=0;
            for(int i=n-2; i>=0; i--)
            {
                int t=str[i]-'0';
                add(t);
                for(int k=t+1; k<10; k++)
                {
                    if(ok(k))
                    {
                        flag=1;
                        jian(k);
                        str[i]=k+'0';
                        break;
                    }
                }
                if(flag)
                {
                    fun(i+1);
                    break;
                }
            }
            if(!flag)
            {
                printf("1");
                fun(0);
            }
        }
        puts(str);
    }
    return 0;
}



评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值