暴力求解法 之 简单枚举

来源:互联网 发布:js format用法 编辑:程序博客网 时间:2024/04/28 04:27
1、除法
    输入正整数n,按从小到大的顺序输出所有形如abcde / fghij = n的表达式,其中a~j恰好为0~9的一个排列,2<=n<=79.
    样例输入:62
    样例输出:  79546 / 01283 =62
                      94736 / 01528 =62
分析: 枚举0~9的所有排列?没这个必要。只需要枚举fghij就可以算出abcde,然后判断是否所有数字都不相同即可。不仅程序简单,而且枚举量也从10!=3628800降低至不到1万。
[cpp] view plaincopy
  1. #include<stdio.h>  
  2. #include<string.h>  
  3. int main()  
  4. {  
  5.     int i,j,n,s1,s2,flag[10];  
  6.     while(~scanf("%d",&n))  
  7.     {  
  8.         for(i=1234;i<5000;i++)  
  9.         {  
  10.             memset(flag,0,sizeof(flag));  
  11.             /*flag保存每一位数字*/  
  12.             s1=i;  
  13.             s2=i*n;  
  14.             while(s1||s2)  
  15.             {  
  16.                 if(!flag[s1%10])  
  17.                 {  
  18.                     flag[s1%10]=1;  
  19.                     s1/=10;  
  20.                 }  
  21.                 else  
  22.                     break;  
  23.                 if(!flag[s2%10])  
  24.                 {  
  25.                     flag[s2%10]=1;  
  26.                     s2/=10;  
  27.                 }  
  28.                 else  
  29.                     break;  
  30.             }  
  31.             for(j=0;j<10;j++)  
  32.               if(!flag[j])  
  33.                   break;  /*判断是否是10个各不相同的数字*/  
  34.             if(j==10&&i*n<=98765) /*如果数字各不相同*/  
  35.             {  
  36.                 if(i<10000) /*除数是一个四位数,有前导0*/  
  37.                   printf("%d / 0%d = %d\n",i*n,i,n);  
  38.                 else  
  39.                   printf("%d / %d = %d\n",i*n,i,n);  
  40.             }  
  41.         }  
  42.     }  
  43.   <span style="font-family: Arial, Helvetica, sans-serif;">                                                       </span>  
                                                                   2、最大乘积
输入n个元素组成的序列s,你需要找出一个乘积罪的的连续子序列。如果这个罪的的乘积不是正数,输出-1.1<=n<=18,-10<=Si<=10;
样例输入:
3
2 4 -3
5
2 5 -1 2 -1
样例输出:
20
分析:连续子序列有两个要素:起点和终点,因此只需枚举起点和终点即可。由于每个元素的绝对值不超过10,一共又不超过18个元素,最大可能的乘积不会超过10^18,可以用long long 存下。
[cpp] view plaincopy
  1. #include<stdio.h>  
  2. #include<string.h>  
  3. const int inf=999999;  
  4. int main()  
  5. {  
  6.     long long a[20],s[20];  
  7.     long long i,j,n,max;  
  8.     while(~scanf("%lld",&n))  
  9.     {  
  10.         memset(s,0,sizeof(s));  
  11.         s[0]=1;  
  12.         max=-inf;  
  13.         for(i=1;i<=n;i++)  
  14.         {  
  15.             scanf("%lld",&a[i]);  
  16.             s[i]=s[i-1]*a[i];  
  17.             /*s[i]表示从第一个数到第i个数的乘积*/  
  18.         }  
  19.         for(i=1;i<=n;i++) /*子序列长度*/  
  20.         {  
  21.             for(j=i;j<=n;j++)  
  22.             {  
  23.                 if(s[j]/s[j-i]>max)  
  24.                   max=s[j]/s[j-i];  
  25.             }  
  26.         }  
  27.         if(max<0)  
  28.            max=-1;  
  29.         printf("%lld\n",max);  
  30.     }  
  31.     return 0;  
  32. }  


 
                                              3、分数拆分
输入正整数k,找到所有的正整数x>=y,使得1/k=1/x + 1/y;
样例输入:
2
12
样例输出:
2
1/2 = 1/6 + 1/3
1/2 = 1/4 + 1/4
8
1/12 = 1/156 + 1/13
1/12 = 1/84 + 1/14
1/12 = 1/60 + 1/15
1/12 = 1/48 + 1/16
1/12 = 1/36 + 1/18
1/12 = 1/30 + 1/20
1/12 = 1/28 + 1/21
1/12 = 1/24 + 1/24
从1/12=1/156+1/13可以看出,x可以比y大很多。由于x>=y,有1/x<=1/y,因此1/k-1/y<=1/y,即y<=2*k.这样,只需要在2*k范围之内枚举y,然后根据y尝试计算出x即可。
[cpp] view plaincopy
  1. #include<stdio.h>  
  2. #include<string.h>  
  3. struct integer  
  4. {  
  5.     int X,Y;  
  6. }a[10000];  
  7. int main()  
  8. {  
  9.     int i,j,y,k,count;  
  10.     while(~scanf("%d",&k))  
  11.     {  
  12.         memset(a,0,sizeof(a));  
  13.         i=count=0;  
  14.         for(y=k+1;y<=k*2;y++)  
  15.         {  
  16.             if(y*k%(y-k)==0)  
  17.             {  
  18.                 count++;  
  19.                 a[i].X=y*k/(y-k);  
  20.                 a[i++].Y=y;  
  21.             }  
  22.         }  
  23.         printf("%d\n",count);  
  24.         for(j=0;j<i;j++)  
  25.             printf("1/%d = 1/%d + 1/%d\n",k,a[j].X,a[j].Y);  
  26.     }  
  27.     return 0;  
  28. }  

                                                                                              4、双基回文数
 如果一个正整数n至少在两种不同的禁止下b1和b2下都是回文数(2<=b1,b2<=10),则称n是双基回文数(注意,回文数不能包含前导零)。输入正整数S<10^6,输出比S大的最小的双基回文数。
样例输入:  1600000
样例输出:  1632995
分析:最自然的想法就是:从n+1开始依次判断每个数是否为双基回文数,而在判断时枚举所有可能的基数(2~10),一切都是那么的“暴力”。令人有些意外的是:这样做对于S<10^6这样的“小规模数据”来说是足够快的——双基回文数太多太密了。
[cpp] view plaincopy
  1. #include<stdio.h>  
  2. int a[30];  
  3. int huiwen(int s[],int n) /*判断是否回文*/  
  4. {  
  5.     int i;  
  6.     for(i=0;i<=n/2;i++)  
  7.     {  
  8.         if(a[i]!=a[n-i])  
  9.         {  
  10.             return 0;  
  11.             break;  
  12.         }  
  13.     }  
  14.     return 1;  
  15. }  
  16. int converse(int n,int k) /*把十进制的n转化为k进制*/  
  17. {  
  18.     int flag=0,i,j=0;  
  19.     while(n)  
  20.     {  
  21.         a[j++]=n%k;  
  22.         n/=k;  
  23.     }  
  24.     if(huiwen(a,j-1))  
  25.       flag=1;   
  26.     if(flag)  /*n在k进制下是回文数*/  
  27.       return 1;  
  28.     else  
  29.       return 0;  
  30. }  
  31. int main()  
  32. {  
  33.     int i,j,k,n,cnt;  
  34.     while(~scanf("%d",&n))  
  35.     {  
  36.         for(j=n+1;;j++)  
  37.         {  
  38.             int p=0;  
  39.             for(i=2,cnt=0;i<=10;i++)  
  40.             {  
  41.                 if(converse(j,i))  
  42.                    cnt++;  /*记录回文次数*/  
  43.                 if(cnt>=2)  /*是双基回文数*/  
  44.                 {  
  45.                     p=1;  
  46.                     break;  
  47.                 }  
  48.             }  
  49.             if(p)  
  50.             {  
  51.                 printf("%d\n",j);  
  52.                 break;  
  53.             }  
  54.         }  
  55.     }  
  56.     return 0;  
  57. }  
0 0
原创粉丝点击