PTA:Have Fun with Numbers

Have Fun with Numbers

Notice that the number 123456789 is a 9-digit number consisting exactly the numbers from 1 to 9, with no duplication. Double it we will obtain 246913578, which happens to be another 9-digit number consisting exactly the numbers from 1 to 9, only in a different permutation. Check to see the result if we double it again!

Now you are suppose to check if there are more numbers with this property. That is, double a given number with k digits, you are to tell if the resulting number consists of only a permutation of the digits in the original number.
Input Specification:

Each input contains one test case. Each case contains one positive integer with no more than 20 digits.

Output Specification:

For each test case, first print in a line “Yes” if doubling the input number gives a number that consists of only a permutation of the digits in the original number, or “No” if not. Then in the next line, print the doubled number.
Sample Input:

1234567899

Sample Output:

Yes
2469135798

思路

由题干的信息可以发现,测试例子是不多于20位的数字
且已知long long的上限也仅只能到达19位
由此,笔者尝试使用STL中的vector容器利用字符串实现庞大数字的加减
这是笔者想到的较为简便的解法:

解题

部分实现:

#include <iostream>
#include <vector>

using namespace std;

vector<char> multi(vector<char> &str)
{
    vector<char> str0;
    int *arr=new int[str.size()];
    int len=str.size(),i,j;
    for(i=len-1,j=0;i>=0;i--,j++)
        arr[j]=(str[i]-'0')*2;
    char x;
    x=(arr[0]>=10)?(arr[0]-10+'0'):(arr[0]+'0');
    str0.push_back(x);
    for(i=1;i<len;i++)
    {
        if(arr[i-1]>=10)
            x=((arr[i]>=10)?(arr[i]-10+'0'):(arr[i]+'0'))+1;
        else
            x=(arr[i]>=10)?(arr[i]-10+'0'):(arr[i]+'0');
        str0.push_back(x);
    }
    if(arr[i-1]>=10) str0.push_back('1');
    return str0;
}

bool judge(vector<char> &str1,vector<char> &str2)
{
    int result=0;
    int len1=str1.size();
    int len2=str2.size();
    if(len1!=len2) return false;
    for(int i=0;i<len1;i++)
        result^=(str1[i]^str2[i]);
    if(result) return false;
    return true;
}

int main()
{
    vector<char> num;
    while(1)
    {
        char x;
        cin.get(x);
        if(x=='\n') break;
        num.push_back(x);
    }
    vector<char> num0=multi(num);
    if(judge(num,num0))
        cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
    for(int i=num0.size()-1;i>=0;i--)
        cout<<num0[i];
    return 0;
}

在五个测试节点中始终有一个无法通过,起初始终不能理解
经过仔细思考,笔者发现
函数:

bool judge(vector<char> &str1,vector<char> &str2)
{
    int result=0;
    int len1=str1.size();
    int len2=str2.size();
    if(len1!=len2) return false;
    for(int i=0;i<len1;i++)
        result^=(str1[i]^str2[i]);
    if(result) return false;
    return true;
}

是通过位运算异或判断两个vector容器是否完全一致
int类型变量result
若为0,则返回真
若为1,则返回假

这里有一个较为严重的漏洞,比如测试用例
123456798
输出
Yes
246913596

这里就能明显发现,结果中 6 和 9 重复出现
而导致在异或的过程中, 6 和 9 的异或代替了 7 和 8 的异或
其实在二进制表示中如果没有产生进位,那么运算符 ^ 和 + 是可以等价的
所以凑巧运算结果是一致的
这导致了结果的错误和测试不通过
由于水平有限,笔者为保证程序的正确性只能将原函数进行了相对复杂的改变
将原有的 O(n) 变为了 O(n^2),代码也相应变长了一点

完全实现:

#include <iostream>
#include <vector>

using namespace std;

vector<char> multi(vector<char> &str)
{
    vector<char> str0;
    int *arr=new int[str.size()];
    int len=str.size(),i,j;
    for(i=len-1,j=0;i>=0;i--,j++)
        arr[j]=(str[i]-'0')*2;
    char x;
    x=(arr[0]>=10)?(arr[0]-10+'0'):(arr[0]+'0');
    str0.push_back(x);
    for(i=1;i<len;i++)
    {
        if(arr[i-1]>=10)
            x=((arr[i]>=10)?(arr[i]-10+'0'):(arr[i]+'0'))+1;
        else
            x=(arr[i]>=10)?(arr[i]-10+'0'):(arr[i]+'0');
        str0.push_back(x);
    }
    if(arr[i-1]>=10) str0.push_back('1');
    return str0;
}

bool judge(vector<char> &str1,vector<char> &str2)
{
    int count=0;
    int len1=str1.size();
    int len2=str2.size();
    if(len1!=len2) return false;
    for(int i=0;i<len1;i++)
    {
        count=0;
        for(int j=0;j<len1;j++)
            if(str2[j]!=str1[i]) count++;
        if(count==len1) return false;
    }
    return true;
}

int main()
{
    vector<char> num;
    while(1)
    {
        char x;
        cin.get(x);
        if(x=='\n') break;
        num.push_back(x);
    }
    vector<char> num0=multi(num);
    if(judge(num,num0))
        cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
    for(int i=num0.size()-1;i>=0;i--)
        cout<<num0[i];
    return 0;
}

其中修改函数:

bool judge(vector<char> &str1,vector<char> &str2)
{
    int count=0;
    int len1=str1.size();
    int len2=str2.size();
    if(len1!=len2) return false;
    for(int i=0;i<len1;i++)
    {
        count=0;
        for(int j=0;j<len1;j++)
            if(str2[j]!=str1[i]) count++;
        if(count==len1) return false;
    }
    return true;
}

解决了以后确实长舒一口气,这个问题确实困扰了身为咸鱼的笔者一段时间
希望也能给大家一点帮助吧(手动滑稽)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值