ZOJ 3327 Friend Number(数学啊 )

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=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

Author: CAO, Peng

Source: The 7th Zhejiang Provincial Collegiate Programming Contest

思路:摘自:http://blog.csdn.net/cnh294141800/article/details/23203947

1.首先判断下有几个0,有一个0的话,

一  。判断0后面有没有比9小的数,有的话那个数加1就可以直接输出了。

二  。如果0是最后一位,前面有比9小的数,那个数+1,后面全输出0即可

三  。如果0是最后一位,前面没有比9小的那直接在最前面加1,后面全输出0即可。

四  。如果0后面没有比9小的,那直接把0位置变成1,后面都变成0输出即可。

2.如果是有多个0的话

一。如果在最右0之后有比9小的数,那直接那个数+1 输出答案即可。

二。如果没有的话,那就直接把这个位置的0变成1,后面全部输出0即可。

3。就是比较一般的情况

这种是比较简单的。统计因子2 3 5 7 出现的次数。

因为4可以由 2×2   组成,6可以由 2×3 组成  8 9都可以组成,所以只要保留素数因子即可。

然后直接从后往前面遍历,用直接已经有的因子数,看能不能组成比这个大的,如果可以的话,高位直接不动,这个位置变成这个数。

然后从最后一位开始,把当前拥有因子能组成的最大数组合起来,一个一个往前放,没有因子的话,那都放1就可以了,然后输出答案即可。

如果都没有可能的话,那在这个数前面加1即可。!!!!!!!!!!

!!!!!!!!

比如111126

一开始 a[2]=a[3]=a[5]=a[7]=0;

然后6遍历到6,a[2]++,a[3]++;

因为没有能组成比6 大.

然后遍历2这个时候a[2]=2,a[3]=1;

能组成3那这个位置就放3此时a[2]=2,a[3]=0;

最后一个变成4输出答案即可。

代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
int n;
char s[10047];
LL c[10];//保存大数
int x[4]= {2,3,5,7};
int len;
void add(int n)
{
    if(n == 1)
        return ;
    for(int i = 0; i <= 3; i++)
    {
        while(n%x[i] == 0)
        {
            c[x[i]]++;
            n/=x[i];
        }
    }
}

void Delete(int n)
{
    if(n == 1)
        return ;
    for(int i = 0; i <= 3; i++)
    {
        while(n%x[i] == 0)
        {
            c[x[i]]--;
            n/=x[i];
        }
    }
}

int judge(int n)//判断是否能组成某个数
{
    if(n == 1)
        return 1;
    for(int i = 0; i <= 3; i++)
    {
        int k = 0;
        while(n%x[i] == 0)
        {
            k++;
            n/=x[i];
        }
        if(k > c[x[i]])//用的每个数字的次数不能大于已有的2 3 5 7 的个数
        {
            return 0;
        }
    }
    return 1;
}

void update(int n)
{
    for(int i = len-1; i >= n; i--)
    {
        for(int j = 9; j >= 1; j--)
        {
            if(judge(j))
            {
                Delete(j);
                s[i] = j+'0';
                break;
            }
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(c, 0,sizeof(c));
        scanf("%s",s);
        len = strlen(s);
        int cont = 0;
        for(int i = 0; i < len; i++)
        {
            if(s[i] == '0')
            {
                cont++;
            }
        }
        int flag = 0;
        if(cont == 1 && s[len-1] == '0')//只有一个零且是最后一个数字
        {
            flag = 0;
            for(int i = len-2; i >= 0; i--)
            {
                s[i]++;
                if(s[i] > '9')
                {
                    s[i] = '0';
                }
                else
                {
                    flag = 1;
                    break;
                }
            }
            if(!flag)
            {
                printf("1");//如果全是9 就在首尾多数出一个1
            }
        }
        else if(cont >= 1)//只有一个零但是不是最后一个 或者 不止一个零
        {
            //含有零 最后的乘积都是零 所以只需要从后开始寻找一个数字加1即可
            for(int i = len-1; i >= 0; i--)
            {
                s[i]++;
                if(s[i] > '9')
                {
                    s[i] = '0';
                }
                else
                {
                    break;
                }
            }
        }
        else
        {
            add(s[len-1]-'0');//统计2 3 5 7 的个数,因为4 6 8 9 可以有前面的数字组成
            flag = 0;
            for(int i = len-2; i >= 0; i--)
            {
                int tt = s[i] -'0';
                add(tt);
                for(int j = tt+1; j < 10; j++)//能否由已有的2 3 5 7组成比t大的数字
                {
                    if(judge(j))
                    {
                        flag = 1;
                        Delete(j);
                        s[i] = j+'0';//更新为当前可以组成的数字
                        break;
                    }
                }
                if(flag)
                {
                    update(i+1);
                    break;
                }
            }
            if(!flag)//如果都没有可能的话,那在这个数前面加1即可
            {
                printf("1");
                update(0);
            }
        }
        printf("%s\n",s);
    }
    return 0;
}

/*
99
10
12
19
222
9099
90099
*/
时间: 2024-10-20 00:01:53

ZOJ 3327 Friend Number(数学啊 )的相关文章

zoj 3327 Friend Number 贪心

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

HDU 4937 Lucky Number (数学,进制转换)

题目 参考自博客:http://blog.csdn.net/a601025382s/article/details/38517783 //string &replace(iterator first0, iterator last0,const_iterator first, const_iterator last); //把[first0,last0)之间的部分替换成[first,last)之间的字符串 /* 题意: 我们将3,4,5,6认为是幸运数字.给定一个十进制数n. 现在可以讲起任意转

HDU 1018 Big Number 数学题解

Problem Description In many applications very large integers numbers are required. Some of these applications are using keys for secure transmission of data, encryption, etc. In this problem you are given a number, you have to determine the number of

ZOJ 3622 Magic Number 打表找规律

A - Magic Number Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Practice ZOJ 3622 Appoint description: Description A positive number y is called magic number if for every positive integer x it satisfies that

ZOJ 3233 Lucky Number

Lucky Number Time Limit: 5000ms Memory Limit: 32768KB This problem will be judged on ZJU. Original ID: 323364-bit integer IO format: %lld      Java class name: Main Watashi loves M mm very much. One day, M mm gives Watashi a chance to choose a number

ZOJ 3436 July Number(DFS)

题意   把一个数替换为这个数相邻数字差组成的数  知道这个数只剩一位数  若最后的一位数是7  则称原来的数为 July Number  给你一个区间  求这个区间中July Number的个数 从7开始DFS  位数多的数总能由位数小的数推出 #include <bits/stdc++.h> using namespace std; const int N = 1e6; int july[N], n; set<int> ans; int pw[] = {1, 10, 100,

ZOJ 3622 Magic Number(数)

题意  假设一个正整数y满足  将随意正整数x放到y的左边得到的数z满足 z%y==0  那么这个数就是个Magic Number   给你一个范围  求这个范围内Magic Number的个数 令 l表示y的位数  ly=10^l  那么z=x*ly + y  要z%y==0   easy看出  仅仅需 x*ly%y==0 又由于x是随意的  所以一个Magic Number必须满足 ly%y==0 y<2^31  所以l最大为10 直接枚举l  找到全部符合的y即可了 当 ly%y==0  

ZOJ 3690 Choosing number(矩阵快速幂)

题目地址:ZOJ 3690 假设F(n)表示前n个人第n个人选择的数大于k的个数,G(n)表示的是前n个人第n个人选择的数小于等于k的个数 那么F(n) = F(n-1)*(m-k)+G(n-1)*(m-k) , G(n) = F(n-1)*k+G(n-1)*(k-1) , 那么最后的结果就是F(n)+G(n); 那么我们可以构造出矩阵 | m-k m-k|   | F(n-1) |       | F(n) | | k      k-1| * | G(n-1) | => | G(n) | 那么

ZOJ 2829 Beautiful Number(睡前一水)

链接:click here 题意:输出第N个能被3或者5整除的数,注意是||而不是&&. 代码: <pre name="code" class="cpp">//zoj 2829 #include <stdio.h> #include <stdlib.h> #include <iostream> #include <string.h> #include <math.h> using