1023. Have Fun with Numbers (20)
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 file 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:1234567899Sample Output:
Yes 2469135798
类型:大数运算
题目大意:给出一个长度不超过20的整数,问这个整数两倍后的数位是否为原数位的一个排列。不管是yes还是no最后都要输出整数乘以2的结果(1)1、用一个数组来统计原来数字使用0-9的个数,然后将该数*2,对使用数字进行减一操作,然后遍历判断是否都等于一即可。
#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
char num1[25];
char num2[25];
int c[10];//记录0-9数字的使用个数
void printnum2(char *str)
{
for(int i=(int)strlen(str)-1;i>=0;--i)
cout<<str[i];
cout<<endl;
}
int main()
{
//freopen("in.txt","r",stdin);
cin>>num1;
for(int i=0;i<(int)strlen(num1);++i)
++c[num1[i]-'0'];//统计数字的使用个数
int carry=0;
int index=0;
for(int i=(int)strlen(num1)-1;i>=0;--i)
{
int digit=(2*(num1[i]-'0')+carry)%10;
c[digit]--;
num2[index++]=digit+'0';
carry=(2*(num1[i]-'0')+carry)/10;
}
//strrev(num2);只在某些编译器存在,g++没有这个函数
if(strcmp(num1,num2)==0)//排除0
{
cout<<"No"<<endl;
cout<<num1<<endl;
return 0;
}
else if(carry==1)//排除*2位数变多的情况
{
cout<<"No"<<endl;
cout<<carry;
printnum2(num2);
}
else
{
for(int i=0;i<10;++i)
{
if(c[i]!=0)
{
cout<<"No"<<endl;
printnum2(num2);
return 0;
}
}
cout<<"Yes"<<endl;
printnum2(num2);
}
return 0;
}
(2)分析:使用char数组存储这个数,没个数的数位乘以2 + 进位,同时设立book来标记数位出现的情况。只有最后book的每个元素都是0的时候才说明这两个数字是相等的一个排列结果#include <cstdio>
#include <string.h>
using namespace std;
int book[10];
int main() {
char num[22];
scanf("%s", num);
int flag = 0;
int len = strlen(num);
for(int i = len - 1; i >= 0; i--) {
int temp = num[i] - '0';
book[temp]++;
temp = temp * 2 + flag;
flag = 0;
if(temp >= 10) {
temp = temp - 10;
flag = 1;
}
num[i] = (temp + '0');
book[temp]--;
}
int flag1 = 0;
for(int i = 0; i < 10; i++) {
if(book[i] != 0)
flag1 = 1;
}
if(flag == 1 || flag1 == 1) {
printf("No\n");
} else {
printf("Yes\n");
}
if(flag == 1)
printf("1");
for(int i = 0; i < len; i++) {
printf("%c", num[i]);
}
return 0;
}
(3)
分析:
给你一个数(大数),判断其*2的结果数是否和原数是一样的排列,注意这里不是说给出的数都是1-9的排列,只是题目中举例子用到了1-9而已。
这里设置了ans[]数组,对于原数的每个数都++,对于结果数的每个数都--,那么最后只要判断ans是否全都0就可以判断原数和结果数是否是相同的排列
注意:
考虑到进位,乘以2以后可能会多出一位,而且20位的数字要用string表示而不是用long long表示。
可以看到以下数字的表示范围中long long不够20位。
int ,long , long long类型的范围
unsigned int 0~4294967295
int 2147483648~2147483647
unsigned long 0~4294967295
long 2147483648~2147483647
long long的最大值:9223372036854775807 (刚好19位)
long long的最小值:-9223372036854775808
unsigned long long的最大值:18446744073709551615
__int64的最大值:9223372036854775807
__int64的最小值:-9223372036854775808
unsigned __int64的最大值:18446744073709551615
#include<stdio.h>
using namespace std;
int ans[10];
char num1[22];
char num2[22];
int main(void){
//freopen("F://Temp/input.txt", "r", stdin);
while (scanf("%s", num1) != EOF){
for (int k = 0; k< 10; k++){
ans[k] = 0;
}
int di = 0, jin = 0,ji = 0;
int i;
for (i = 21; num1[i] == 0; i--);//找到最后一位的下标开始计算
for ( ; i >= 0; i -- ){
ji = (num1[i] - '0') * 2;
ans[num1[i] - '0'] ++;//ans对原数相应位的个数++
di = ji % 10;//*2后的当前位的数字
num2[i] = di + jin + '0';
ans[num2[i] - '0'] --;//ans对结果数的相应位的个数--
jin = (ji + jin) / 10;
}
if (jin != 0)ans[jin] ++;
for (i = 1; i < 10; i++){
if (ans[i] != 0)break;
}//判断ans是否全部都为0,若是,则说明原数和结果数是相同的排列
if (i == 10){
puts("Yes");
}
else {
puts("No");
}
if (jin != 0)printf("%d", jin);
puts(num2);
}
return 0;
}