HDOJ  1271   整数对

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1271

    这个题目的思路,是这样的我们假设数字A是这样的一个数字 a*(10^(k+1)) + b*(10^k) + c 其中 a 为任意数字,b为去掉的那一位数字,范围 [0,9] 的整数,c<10^k 。则去掉b后的数字B为 a*(10^k) + c ,而A+B的值可以用一下式子表示 (11*a+b)*(10^k) + 2*c 这个值等于 n , 我们枚举 k的值,从0到10 ,对于取定的k值,显然有一下对应 2*c = n%(10^k) 或者 2*c = n%(10^k) + 10^k ; 可以求出整数c的值,然后枚举 b的值,来确定a的值,使得a的值为整数 /..计算中可能会出现重复的结果,输出是记得要处理一下#include<iostream>
#include<algorithm>
using namespace std;
int re[100];
int main()
{
    int n,a,i,j,k,num,x,y,temp,tt;

    while(scanf("%d",&n) &&n)
    {
        num = 0,tt = 1;
        for(k =0; k <= 10; k ++)
        {
            for(j = 0; j < 2; j ++)
            {
                y = n% tt,x = n/tt;
                if(j == 1)
                    y += tt,x --;
                if(x > 0 && y % 2 == 0)
                {
                    for(i = 0; i <= 9; i ++)
                    {
                        if((x-i) == 0)
                        {
                            a = (x-i)/11;
                            temp = tt*(a*10 +i) + y/2;
                            re[num++] = temp;   
                        }
                    }
                }
            tt *= 10;
        }
        sort(re,re+num);
        if(num == 0)   
            printf("No solution.\n");
        else{
            printf("%d",re[0]);
            for(i =1; i < num; i ++)
                if(re[i] != re[i-1])    printf(" %d",re[i]);
            printf("\n");
        }
    }
    return 0;
}

******************************************************************************************

还有一种代码感觉也可以....

解题思路:插入比较

设B=Bn,Bn-1,...B2,B1   枚举是再哪个位置插入了个位数k...比如枚举是第i位后面插入了个位数k..那么得到的N=11*(Bn,Bn-1,...Bk+1)*(10^(i+1))+k*(10^i)+2*(Bk-1..B2,B1)
应该不难理解吧...题目是给出了N...那么就反过来推了..看我程序吧..注意的就是一些情况的处理..如:
推出的中间数必须是个位数(有可能得到10..那么显然这个数是要不得的.)..
末尾的(Bk-1...B2,B1)不一定就是(Nk-1...N2,N1)/2阿..有可能是(1,Nk...N2,N1)/2...就如同后缀为2的..可能是1+1=2的2..也可能是6+6=12的2..
要排除10=05+5的这种错误情况..就是前缀和中间个位数不能同时为0..
 最后..输出的时候让相同的数只输出一个...

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int N,B,k,x,y,i,m,ans[1000],num;
int main()
{
       while (~scanf("%d",&N))
       {
             if (!N) break;
             num=0;
             y=N/11; x=N;
             if (x<10) ans[++num]=y*10+x;
             i=10;
             if (N%2!=1)
             while (i<=N)
             {
                   x=(N%i)/2;
                   m=N/i;
                   y=m/11;
                   k=m;
                   if (k<10)
                   {
                         k=y*(i*10)+k*i+x;
                         ans[++num]=k;
                   }
                   x=(N%i+i)/2;
                   k=m-1;
                   if (k>=0 && (y || k))
                   {
                         k=y*(i*10)+k*i+x;
                         ans[++num]=k;
                   }
                   i*=10;
             }
             if (!num) printf("No solution.\n");
             else
             {
                   sort(ans+1,ans+1+num);
                   printf("%d",ans[1]);
                   for (i=2;i<=num;i++)
                     if (ans[i]!=ans[i-1]) printf(" %d",ans[i]);
                   printf("\n");
             }
       }
       return 0;
}

下面这一种思路与上面差不多,但又有一点点不同

******************************************************************************************

假设A中去掉的数在第k+1位,可以把A分成三部分,低位,k,和高位。

A == a + b * 10^k + c * 10^(k+1)

B == a                 c * 10^k

N == A + B == 2 * a + b * 10^k + c * 10^k * 11

其中b是一位数, b * 10^k 不会进位,用 10^k 除 N 取整就可以得到 b + 11c ,再用 11 除,商和余数就分别是 c 和 b 了。但是这里有个问题 a 是一个小于 10^k 的数没错,但是 2a 有可能产生进位,这样就污染了刚才求出来的 b + 11c 。但是没有关系,因为进位最多为 1 ,也就是 b 可能实际上是 b+1 , b 本来最大是 9 ,那现在即使是 10 ,也不会影响到除 11 求得的 c 。因此 c的值是可信的。然后根据 2a 进位和不进位两种情况,分别考虑 b 要不要 -1 ,再求 a ,验算,就可以了。

迭代k从最低位到最高位做一遍,就可以找出所有可能的 A 。

#include<stdio.h>
#include<stdlib.h>
int cmp(const void *a,const void *b)
{
 return *(int *)a-*(int *)b;
}
int main()
{
 int n,i,k,a,b,c,x[20];
 while(scanf("%d",&n)&&n)
 {
  i=0;
  for(k=1;k<=n;k*=10)
  {
   c=(n/k)/11;
   b=n/k-c*11;
   if((b!=0||c!=0)&&b<10)
   {
    a=(n-b*k-c*11*k)/2;
    if(2*a+b*k+c*11*k==n)
     x[i++]=a+b*k+c*10*k;
   }
   b--;
   if((b!=0||c!=0)&&b>=0)
   {
    a=(n-b*k-c*11*k)/2;
    if(2*a+b*k+c*11*k==n)
     x[i++]=a+b*k+c*10*k;
   }
  }
  if(i)
  {
   qsort(x,i,sizeof(x[0]),cmp);
   printf("%d",x[0]);
   for(k=1;k<i;++k)
   {
    if(x[k]!=x[k-1]) printf(" %d",x[k]);
   }
   puts("");
  }
  else printf("No solution.\n");
 }
 return 0;
}

最后还有一种用的是set,顺便鉴赏一下

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
void solve(int x,set<int> &result){
    int k,high,b2,a;
    int c,sum,b1;
    for(k=1;k<=x;k*=10){
        high=x/k;
        c=high/11;
        c*=k;
        b1=high;
        if((b1!=0||c!=0)&&b1<10){
            b1*=k;
            a=(x-b1-11*c)/2;
            if(2*a+b1+11*c==x)
                result.insert(a+b1+c*10);  
        }
        b2=high-1;
        if((b2!=0||c!=0)&&b2>=0){
            b2*=k;
            int a2=(x-b2-11*c)/2;
            if(x==2*a2+b2+11*c)
                result.insert(a2+b2+10*c);
        }
    }
}
int main(){
    int x,i;
    while(cin>>x,x){
        set<int>result;
            //set结构不仅可以排序,而且可以去除重复的
        solve(x,result);
        if(result.empty()){
            printf("No solution.\n");
        }
        else{
            set<int>::iterator it=result.begin();
            printf("%d",*it);
            while(++it!=result.end())
                printf(" %d",*it);
            printf("\n");
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值