• poj2325 Persistent Numbers ****


    /*
    * 简略版大整数除法 + 贪心
    * 不难发现,如果输入的数含有大于等于10的质数因子,则无解,所以
    * ,只需要把输入的数分解为2,3,5,7的幂的形式,然后再由低位向
    * 高位进行分配即可(越低位的数字,其值尽可能大)
    *
    * 开始没好好分析,结果认为 只要 从高位向低位枚举,且满足( ans[i+1] >= ans[i] && ans[i+1]*ans[i] >= 10 )即可,
    * 每次枚举一个,就将原数除这个数。。。一次递归求每一位数。 只要求出了一个答案,则答案就是这个。。
    * 后来发现这个方法是不行的。。 比如:54454680 找到的答案是:2566777779 有10位。。。 而正确答案是:577777899 有9位
    * 所以要找到正确答案,就要求出所有可能的答案然后取最小的那个。。这要就TLE了。。。所以这个方法有不可克服的困难,只好放弃。
    * (代码附在后面,以此为鉴)
    *
    * 然后就用最开始讲的那个算法。。这就很简单了。。。
    *
    */

    #include
    <cstdio>
    #include
    <cstring>
    using namespace std;

    const int maxN = 1000 + 5, p2 = 0, p3 = 1, p5 = 2, p7 = 3;
    char cData[maxN]; //输入
    int data[maxN], len; //个位数放在data[0]
    int prime[4] = {2, 3, 5, 7}, ans[5] = {}, lastAns[maxN]={};//ans:各个素因子的个数。。 lastAns:最终答案


    //大整数a 除以 i.. 由于i是个位数,,所以这个大整数除法很简单, a最多maxLen位
    int inline operate(int *a, int i, int maxLen){
    int ansLen = -1;
    for(int j=maxLen-1; j>0; j--){
    if(a[j] < i){
    a[j
    -1] += a[j]*10;
    a[j]
    = 0;
    }
    else{
    a[j
    -1] += (a[j] % i) * 10;
    a[j]
    = a[j] / i;
    if(ansLen == -1) ansLen = j;
    }
    }
    if(a[0] % i != 0) return 0;
    else{
    a[
    0] = a[0] / i;
    return (ansLen==-1 ? 1 : (ansLen+1)); //注意asnLen要+1
    }
    }

    //求各素因子的个数
    bool solve(int *a, int depth, int maxLen){
    if(depth == 4 && a[0] == 1){ if(maxLen == 1) return true; else return false; }
    else if(depth == 4 && a[0] != 1) return false;
    int tmpA[maxN], nextMaxLen = maxLen;
    memcpy(tmpA, a,
    sizeof(tmpA));
    while(true){
    int opAns = operate(tmpA, prime[depth], maxLen);
    if(opAns){
    ans[depth]
    ++;
    nextMaxLen
    = opAns;
    memcpy(a, tmpA,
    sizeof(tmpA));
    }
    else{ //本素因子已除尽,递归除下一个素因子
    return solve(a, depth+1, nextMaxLen);
    }
    }
    }

    //求最终答案,最高位放在lastAns[0]
    int getAns(){
    int cur = 0;
    while(ans[p3] >= 2){ //9
    lastAns[cur++] = 9; ans[p3] -= 2;
    }
    while(ans[p2] >= 3){ //8
    lastAns[cur++] = 8; ans[p2] -= 3;
    }
    while(ans[p7] >= 1){ //7.。。一次类推
    lastAns[cur++] = 7; ans[p7] -= 1;
    }
    while(ans[p2]>=1 && ans[p3]>=1){
    lastAns[cur
    ++] = 6; ans[p2]--; ans[p3]--;
    }
    while(ans[p5]>=1){
    lastAns[cur
    ++] = 5; ans[p5]--;
    }
    while(ans[p2]>=2){
    lastAns[cur
    ++] = 4; ans[p2] -= 2;
    }
    while(ans[p3]>=1){
    lastAns[cur
    ++] = 3; ans[p3]--;
    }
    while(ans[p2]>=1){
    lastAns[cur
    ++] = 2; ans[p2]--;
    }
    return cur;
    }

    int main(){
    while(scanf("%s", cData)){
    if(cData[0] == '-') return 0;
    len
    = strlen(cData);
    if(len == 1){
    printf(
    "1%s\n", cData);
    continue;
    }

    memset(data,
    0, sizeof(data));
    memset(ans,
    0, sizeof(ans));
    memset(lastAns,
    0, sizeof(lastAns));
    for(int i=0; i<len; i++){
    data[i]
    = cData[len - i -1] - '0';
    }

    if(!solve(data, 0, len)){
    printf(
    "There is no such number.\n");
    }
    else{
    int iMax = getAns();
    for(int i=iMax-1; i>=0; i--){
    printf(
    "%d", lastAns[i]);
    }
    printf(
    "\n");
    }
    }

    return 0;
    }

    ________________________________________________________

    [附]: 错误代码:


    #include <cstdio>
    #include
    <cstring>
    using namespace std;

    const int maxN = 1000 + 5;
    char cData[maxN];
    int data[maxN], tmpAns[maxN], ans[maxN], len;
    int lastAns[maxN];

    /* 这时较完整版大整数除法。。本题用不上
    int minus(int *a, int *b, int maxLen){
    int ansLen;
    for(int i=0; i<maxLen; i++){
    a[i] = a[i] - b[i];
    if(a[i] < 0){
    a[i] += 10; a[i+1]--;
    }
    if(a[i]) ansLen = i + 1;
    }
    return ansLen;
    }

    bool inline getMax(int *a, int *b, int maxLen){
    for(int i=maxLen-1; i>=0; i--){
    if(a[i] > b[i]) return true;
    else if(a[i] < b[i]) return false;
    }
    return true;
    }


    int operate(int *a, int i, int maxLen){
    int ansLen = -1;
    memset(tmpAns, 0, sizeof(int)*maxN);
    if(maxLen == 1){
    if(a[0] % i != 0) return 0;
    else{
    tmpAns[0] += a[0] / i;
    memcpy(a, tmpAns, sizeof(int)*maxN);
    return 1;
    }
    }
    while(true){
    if(maxLen == 1){
    if(a[0] % i != 0) return 0;
    else{
    tmpAns[0] += a[0] / i;
    memcpy(a, tmpAns, sizeof(int)*maxN);
    return ansLen + 1;
    }
    }

    int tmp[maxN] = {}, tmpLen;
    if(a[maxLen-1] > i){
    tmp[maxLen-1] = i;
    tmpLen = maxLen - 1;
    }
    else{
    tmp[maxLen-2] = i;
    tmpLen = maxLen - 2;
    }
    if(ansLen == -1) ansLen = tmpLen;
    int tmpMaxLen;
    while(true){
    tmpMaxLen = minus(a, tmp, maxLen);
    tmpAns[tmpLen]++;
    if(!getMax(a, tmp, maxLen)) break;
    }
    maxLen = tmpMaxLen;
    }
    }
    */

    bool inline getMax(int *a, int *b, int maxLen){
    for(int i=0; i<maxLen; i++){
    if(a[i] > b[i]) return true;
    else if(a[i] < b[i]) return false;
    }
    return false;
    }

    int inline operate(int *a, int i, int maxLen){
    int ansLen = -1;
    for(int j=maxLen-1; j>0; j--){
    if(a[j] < i){
    a[j
    -1] += a[j]*10;
    a[j]
    = 0;
    }
    else{
    a[j
    -1] += (a[j] % i) * 10;
    a[j]
    = a[j] / i;
    if(ansLen == -1) ansLen = j;
    }
    }
    if(a[0] % i != 0) return 0;
    else{
    a[
    0] = a[0] / i;
    return (ansLen==-1 ? 1 : (ansLen+1));
    }
    }

    bool solve(int *a, int maxLen, int lastNum, int ansLen){
    if(maxLen == 1 && a[0] == 1){
    // if(lastAns[0] == -1 || getMax(lastAns, ans, maxN))
    // memcpy(lastAns, ans, sizeof(int)*maxN);
    return true;
    }

    int tmpA[maxN], tmpLen = maxLen;
    memcpy(tmpA, a,
    sizeof(tmpA));
    for(int i=lastNum; i<=9; i++){
    if(ansLen > 0 && i * lastNum < 10) continue;
    if(tmpA[0] % 2 != 0 && i % 2 == 0) continue;

    int opAns = operate(tmpA, i, tmpLen);
    if(!opAns){
    memcpy(tmpA, a,
    sizeof(tmpA));
    continue;
    }

    ans[ansLen]
    = i;

    if(solve(tmpA, opAns, i, ansLen+1)) return true;
    memcpy(tmpA, a,
    sizeof(tmpA));
    }
    }

    int main(){
    while(scanf("%s", cData)){
    if(cData[0] == '-') return 0;
    len
    = strlen(cData);
    if(len == 1){
    printf(
    "1%c\n", cData[0]);
    continue;
    }

    memset(data,
    0, sizeof(data));
    memset(ans,
    0, sizeof(ans));
    memset(lastAns,
    0, sizeof(lastAns));
    lastAns[
    0] = -1;
    for(int i=0; i<len; i++){
    data[i]
    = cData[len - i -1] - '0';
    }

    if(!solve(data, len, 2, 0)){
    printf(
    "There is no such number.\n");
    }
    else{
    for(int i=0; ans[i]!=0; i++){
    printf(
    "%d", ans[i]);
    }
    printf(
    "\n");
    }

    }


    return 0;
    }

  • 相关阅读:
    磁盘挂载自动分区脚本
    docker的私有仓库的搭建
    centos6上安装docker
    docker的本地仓库换成阿里云的镜像仓库
    python中的coding的格式书写形式
    mysql5.6的二进制包安装
    mysql忘记root密码
    Verilog利用$fdisplay命令往文件中写入数据
    Quartus和ISE调用Synplify进行综合的问题
    TMS320C6455 SRIO 实现方案
  • 原文地址:https://www.cnblogs.com/longdouhzt/p/2122078.html
Copyright © 2020-2023  润新知