编程论坛's Archiver

jiang5495 发表于 2008-5-11 17:53

一个编程题目,求解题思路,不要求过程,当然有过程更好,望各位高手不吝赐教!

一个尾数前移问题,
如:102564
它的尾数是4;
将尾数前移得:410256;
而刚好:410256能整除102564且为4;
现在的问题是:
我们将尾数记为:p;
将尾数前移后所得数去整除原数,所得结果记为: q;(前提p能被q整除);
从键盘输入p和q;
从屏幕输出:与之对应的原数;

输入举例:
4 4
输出举例:
102564



我对这个程序是这样实现的:
# include<stdio.h>
void main()
{
long a[11],m,n,i,j,p,q,flag,flagf=0,k;
printf("Please enter two numbers 2<=q<=p<=9!\n");
scanf("%ld%ld",&p,&q);
a[1]=p;
for(a[10]=0;a[10]<=9;a[10]++)
for(a[9]=0;a[9]<=9;a[9]++)
for(a[8]=0;a[8]<=9;a[8]++)
for(a[7]=0;a[7]<=9;a[9]++)
for(a[6]=0;a[6]<=9;a[6]++)
for(a[5]=0;a[5]<=9;a[5]++)
for(a[4]=0;a[4]<=9;a[4]++)
for(a[3]=0;a[3]<=9;a[3]++)
for(a[2]=0;a[2]<=9;a[2]++)
{
for(j=10;j>=2;j--)
{
  if(a[j]!=0)
  {
  flag=j;
  break;}
  }
  m=n=0;
  while(j>=2)
  {
  for(k=1;k<=j-1;k++)
  a[j]=a[j]*10;
  n=n+a[j];
  }
  n=n+a[1];
  j=flag;
  while(j>=2)
  {
  a[j]=a[j]/10;
  m=m+a[j];}
  for(k=1;k<=flag-1;k++)
  a[1]=a[1]*10;
  m=m+a[1];
  if(m%n==0)
  if(m/n==q)
  {
  printf("%ld",n);
  flagf=1;
  break;}
  a[1]=p;
  }
   if(flagf!=1)
   printf("NOt found!\n");
   getch();
   }



下面是我的问题:
我的着个程序陷入了死循环。
但我相信这个题目肯定还有其他解法,望各位高手指教一二;
只要告诉我基本思路就可一了。

广陵绝唱 发表于 2008-5-11 21:51

[code]
/**************************************************************

        利用穷举法求这道题,方法好象愚钝了些,但暂时也就
    会这种方法了。

        如有不对之处,还请大家不吝指教,谢谢。
**************************************************************/
#include<Stdio.h>
#define N 999999
float wei(float a,float b)
{
        if(b>10&&b<100)
                return a*=100;
        else if(b>99&&b<1000)
                return a*=1000;
        else if(b>999&&b<10000)
                return a*=10000;
        else
                return a*=100000;
}
int main(void)
{
        float p,q,a,b;
        printf("请输入两个整数,空格格开,enter结束输入:\n");
        scanf("%f %f",&p,&q);
        for(b=10;b<N;++b)
        {
                a=wei(p,b);
                if((a+b)/(b*10+p)==q)
                {
                        printf("这个数字为:%f\n",b*10+p);
                        break;
                }
        }
        if(b>=N)
                printf("没有您要找的数字。\n");


        getch();
}



        [/code]

雨中飛燕 发表于 2008-5-11 23:30

p和q的范围是什么?

[img]http://blog.programfan.com/upfile/200804/20080430094836.gif[/img][color=white]

广陵绝唱 发表于 2008-5-11 23:40

[quote][bo]以下是引用 [un]雨中飛燕[/un] 在 2008-5-11 23:30 的发言:[/bo]

p和q的范围是什么?
[/quote]
~~~~~~~~~~~~~`
    实在是对不起,这道题我头回见到,所以对它很不了解,所以所用的例子就是用到LZ所用的4、4,结果也是用LZ提供的。我输入5、5,6、6全不行。

    我想这题应该有很成熟的解法与算法,我的代码也算是抛砖引玉吧。

hjh10845 发表于 2008-5-12 00:03

for(a[10]=0;a[10]<=9;a[10]++)
for(a[9]=0;a[9]<=9;a[9]++)
for(a[8]=0;a[8]<=9;a[8]++)
for(a[7]=0;a[7]<=9;a[9]++)
for(a[6]=0;a[6]<=9;a[6]++)
for(a[5]=0;a[5]<=9;a[5]++)
for(a[4]=0;a[4]<=9;a[4]++)
for(a[3]=0;a[3]<=9;a[3]++)
for(a[2]=0;a[2]<=9;a[2]++)
*********************************
是我愚昧还是你弄错,常数也能做“++” 运算?

广陵绝唱 发表于 2008-5-12 00:05

回复 5# 的帖子

其实他用这么多的for本身就是错误的行为——我觉得。

qinxinhai 发表于 2008-5-12 00:06

我真服了
楼上的这些兄弟姐妹们了
我根本就看不懂了!

雨中飛燕 发表于 2008-5-12 00:28

这个题不错,我暂时保留一下我的答案
其中:
5 5 的结果是:
102040816326530612244897959183673469387755
而 6 6 的结果是:
1016949152542372881355932203389830508474576271186440677966
还有 7 5 的结果是:
142857

[img]http://blog.programfan.com/upfile/200804/20080430094836.gif[/img][color=white]

雨中飛燕 发表于 2008-5-12 00:30

其实不必一定整除亦可

[img]http://blog.programfan.com/upfile/200804/20080430094836.gif[/img][color=white]

广陵绝唱 发表于 2008-5-12 00:33

回复 8# 的帖子

你所求的数值太大了,我目前的知识无法将它求出来。

StarWing83 发表于 2008-5-12 05:01

广陵兄,任何事情要认真分析以后才下结论。这道题其实很简单的。
根据LZ的叙述,我们可以得出式子,其中n是m的位数。m是所求的数字。
p*10^n+m
---------=q
m*10+p
这个式子,p,q已知,n可以根据m算出来。似乎已经解决了:枚举m即可。但是从飞燕的结果来看,枚举m显然是不行的。因为位数太多。这时我们可以反其道而求之。我们先假设n已知,把m解出来:
p*10^n+m=10qm+pq
p*10^n=(10q-1)m+qp
m=(10^n-q)p/(10q-1)

这样,我们直接枚举n,然后就可以针对每个n求出一个m。但是除法不一定是整除。那么问题转变为:求最小的n,使上式得出的m为整数。同时m的位数为n。
枚举n的话,问题的复杂度就可以大大降低了。
这道题还需要大数运算的知识,大数除法,整除判断等我还没做过。查完了资料再来看这道题。

StarWing83 发表于 2008-5-12 05:04

飞燕真的很强,一个小时可以写出算法并算出结果。要是我肯定做不到……基础啊………………欠缺基础……

StarWing83 发表于 2008-5-12 05:18

额……百度到两种大数除法的方法,一种是模拟手算,还有一种是用减法和移位实现……想想再说……

雨中飛燕 发表于 2008-5-12 10:09

楼上,你说的方法不好,还不是我所用的方法
还有,假如尾数不一定是一个位,比如是10,要是6的倍数,
那么结果是:
01669449081803005008347245409015025041736227045075125208681135225375626043405676126878130217028380634390651085141903171953255425709515859766277128547579298831385642737896494156928213689482470784641068447412353923205342237061769616026711185308848080133555926544240400667779632721202003338898163606010
(最高位的0必须要保留。。。)

[img]http://blog.programfan.com/upfile/200804/20080430094836.gif[/img][color=white]

juisi 发表于 2008-5-12 10:44

[quote][bo]以下是引用 [un]hjh10845[/un] 在 2008-5-12 00:03 的发言:[/bo]

for(a[10]=0;a[10] [/quote]

a[10]是变量 怎么会是常数呢?

forever74 发表于 2008-5-12 11:12

貌似不用那么复杂,我就说LZ的原始数据
最后一位(尾数)是4,并且把4挪走了以后新数变成原来的4倍,4*4=16,那么新数的个位必定是6还要往高位进一,也就是说原数的十位是6。然后6*4=24,那么新数十位(原数百位)就是24的那个4再加上刚才从后边进上来的1,也就是5,再往更高位进2(24的十位)......

往前递推就可以了。
我这么说不知道说清楚了没有?
假设p,q都是1位数:
[code]#include <stdio.h>
int main()
{
        int a[1000]={0};
        int p,q,jin,i;
        scanf("%d%d",&p,&q);
        a[0]=p;
        i=1;
        while(1)
        {
                jin=a[i-1]*q;
                if(p==a[i]+jin)
                {
                        i--;
                        break;
                }
                a[i]+=jin%10;
                a[i+1]+=jin/10;
                i++;
        }
        while(--i+1)
                printf("%1d",a[i]);
        printf("\n");
        return 0;
}[/code]

[[it] 本帖最后由 forever74 于 2008-5-12 12:24 编辑 [/it]]

StarWing83 发表于 2008-5-12 12:52

恩……递推复杂度的确比枚举低……Orz……
话说,枚举也不高吧?假设答案是m位,枚举也只需要枚举m次而已,每次一次减法,一次乘法,一次除法……
而且并不需要强制规定p是一位,可以稍微改改公式就够了。
前面的0我的方法也可以解决,如果n和m位数不同的话,前补0.

StarWing83 发表于 2008-5-12 12:59

啊……递推其实不需要用到大数运算……Orz……我错了……

雨中飛燕 发表于 2008-5-12 13:41

16楼的代码要是输入 06896551724137931  2 呢?
注意最高位为0的情况(这时是有用的,占位)

[img]http://blog.programfan.com/upfile/200804/20080430094836.gif[/img][color=white]

StarWing83 发表于 2008-5-12 13:49

飞燕,我的5 5的运行结果是:
10204081632653061224489795918367305
经验算也是正确的,但是比你的小……

页: [1] 2 3

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.