2016中國大學生程序設計競賽(長春) Ugly Problem 模擬+大數減法

傳送門:http://acm.hdu.edu.cn/showproblem.php?pid=5920php

咱們的思路是:ios

  1. 對於一個串s,先根據s串前一半複製到後一半構成一個迴文串,
  2. 若是這個迴文串比s小,則作減法並遞歸;
  3. 若是相等直接結束;
  4. 若是大,那麼找前一半離中心最近的一個非零數減1,並把這位以後到中心的數全都變爲9,例如11000->11011,大了,因此變成10901;

ps:由於大數相減要傳指針參數,調了蠻久,發現指針的亂指了,因此開了一個二維數組,每一次算出的原串和迴文串都用新的指針,也就是s[tot],ss[tot],temp[tot];c++

/**************************************************************
    Problem:
    User: youmi
    Language: C++
    Result: Accepted
    Time:
    Memory:
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d\n",a)
#define ptlld(a) printf("%I64d\n",a)
#define rep(i,from,to) for(int i=from;i<=to;i++)
#define irep(i,to,from) for(int i=to;i>=from;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define eps 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl
const double pi=4*atan(1.0);

using namespace std;
typedef long long ll;
template <class T> inline void read(T &n)
{
    char c; int flag = 1;
    for (c = getchar(); !(c >= '0' && c <= '9' || c == '-'); c = getchar()); if (c == '-') flag = -1, n = 0; else n = c - '0';
    for (c = getchar(); c >= '0' && c <= '9'; c = getchar()) n = n * 10 + c - '0'; n *= flag;
}
ll Pow(ll base, ll n, ll mo)
{
    ll res=1;
    while(n)
    {
        if(n&1)
            res=res*base%mo;
        n>>=1;
        base=base*base%mo;
    }
    return res;
}
//***************************

int n;
const int maxn=1000+10;
const ll mod=1000000007;
char ans[100][maxn];
int tot=0;

int Minus(char *source1, char *source2, char *result)//返回:1(s1>s2),-1(s1<s2),0(s1=s2)
{
    int length1 = strlen(source1); // 被減數的長度
    int length2 = strlen(source2); // 減數的長度
    int i, j, k = 0;
    int temp; // 臨時存放位相減的結果
    int bit = 0; // 借位,1表示須要借位,0表示不須要借位
    char ch; // 用於交換
    for (i = length1 - 1, j = length2 - 1; i >= 0 && j >= 0; --i, --j)
    {
        // 計算兩個位之間的差值,同時要考慮借位
        temp = (source1[i] - '0') - (source2[j] - '0') - bit;

        if (temp < 0) // 須要借位
        {
            bit = 1;
            result[k++] = temp + 10 + '0';
        }
        else// 不須要借位
        {
            bit = 0;
            result[k++] = temp + '0';
        }
    }

    while (i >= 0) // length1 > length2的狀況,結果爲正數,將剩餘數據賦值給計算結果數組
    {
        temp = source1[i--] - '0' - bit;
        if (temp < 0) // 須要借位
        {
            bit = 1;
            result[k++] = temp + 10 + '0';
        }
        else
        {
            bit = 0;
            result[k++] = temp + '0';
        }
    }
    while (j >= 0)// length1 < length2的狀況,結果爲負數,將剩餘數據賦值給計算結果數組
    {
        temp = 10 - bit - (source2[j--] - '0');
        result[k++] = temp + '0';
    }

    // 對仍有進位的狀況考慮,主要分兩種:一種是strlen(p1)<strlen(p2),另外一種是p1-p2<0,這兩種狀況bit爲1
    if (bit == 1)
    {
        // 最低位確定不會被借位,因此不須要減去借位
        // 只會向高位借位
        result[0] = 10 - (result[0] - '0') + '0';
        for (i = 1; i < k; i++)
        {
            result[i] = 10 - (result[i] - '0') - bit + '0';
        }
    }

    for (i = k - 1, j = 0; i >= j; --i, ++j)
    {
        ch = result[i];
        result[i] = result[j];
        result[j] = ch;
    }
    result[k] = '\0';
    while(result[0]=='0'&&strlen(result)>1)//去掉前導零
        strcpy(result,result+1);
    if(length1<length2)
        return -1;
    else if(length1>length2)
        return 1;
    else
    {
        for(int i=0;i<length1;i++)
        {
            if(source1[i]>source2[i])
                return 1;
            else if (source1[i]<source2[i])
                return -1;
        }
    }
    return 0;
}
char ss[100][maxn],temp[100][maxn];
char s[100][maxn];
void dfs()
{
    int len=strlen(s[tot]);
    if(len==1)
    {
        strcpy(ans[tot],s[tot]);
        tot++;
        return;
    }
    int half=len/2;
    int pre=-1;
    int num=1-len%2;
    if(len%2==0)
    {
        for(int i=0;i<half;i++)
        {
            if(s[tot][i]!='0')
                pre=max(pre,i);
            ss[tot][i]=s[tot][i];
        }
        for(int i=half;i<len;i++)
            ss[tot][i]=ss[tot][2*half-i-1];
    }
    else
    {
        for(int i=0;i<=half;i++)
        {
            if(s[tot][i]!='0')
                pre=max(pre,i);
            ss[tot][i]=s[tot][i];
        }
        for(int i=half+1;i<len;i++)
            ss[tot][i]=ss[tot][2*half-i];
    }
    ss[tot][len]='\0';
    s[tot][len]='\0';
    int flag=Minus(s[tot],ss[tot],temp[tot]);
    if(flag==-1)
    {
        if(s[tot][pre]=='1'&&pre==0)
        {
            for(int i=0;i<len-1;i++)
                ss[tot][i]='9';
            ss[tot][len-1]='\0';
        }
        else
        {
            ss[tot][pre]=s[tot][pre]-1;
            ss[tot][2*half-pre-num]=s[tot][pre]-1;
            for(int i=pre+1;i<2*half-pre-num;i++)
                ss[tot][i]='9';
        }
        Minus(s[tot],ss[tot],temp[tot]);
        strcpy(ans[tot],ss[tot]);
        strcpy(s[tot+1],temp[tot]);
        tot++;
        dfs();
    }
    else if(flag==0)
    {
        strcpy(ans[tot],ss[tot]);
        tot++;
        return;
    }
    else
    {
        strcpy(ans[tot],ss[tot]);
        strcpy(s[tot+1],temp[tot]);
        tot++;
        dfs();
    }
}
int main()
{
    int kase=0;
    sc(n);
    while(n--)
    {
        printf("Case #%d:\n",++kase);
        tot=0;
        scs(s[tot]);
        while(s[tot][0]=='0'&&strlen(s[tot])>1)//去掉前導零
            strcpy(s[tot],s[tot]+1);
        dfs();
        pt(tot);
        rep(i,0,tot-1)
        puts(ans[i]);
    }
    return 0;
}
相關文章
相關標籤/搜索