程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 暴力求解法 之 簡單枚舉

暴力求解法 之 簡單枚舉

編輯:C++入門知識

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]
#include<stdio.h>  
#include<string.h>  
int main() 

    int i,j,n,s1,s2,flag[10]; 
    while(~scanf("%d",&n)) 
    { 
        for(i=1234;i<5000;i++) 
        { 
            memset(flag,0,sizeof(flag)); 
            /*flag保存每一位數字*/ 
            s1=i; 
            s2=i*n; 
            while(s1||s2) 
            { 
                if(!flag[s1%10]) 
                { 
                    flag[s1%10]=1; 
                    s1/=10; 
                } 
                else 
                    break; 
                if(!flag[s2%10]) 
                { 
                    flag[s2%10]=1; 
                    s2/=10; 
                } 
                else 
                    break; 
            } 
            for(j=0;j<10;j++) 
              if(!flag[j]) 
                  break;  /*判斷是否是10個各不相同的數字*/ 
            if(j==10&&i*n<=98765) /*如果數字各不相同*/ 
            { 
                if(i<10000) /*除數是一個四位數,有前導0*/ 
                  printf("%d / 0%d = %d\n",i*n,i,n); 
                else 
                  printf("%d / %d = %d\n",i*n,i,n); 
            } 
        } 
    } 
  <SPAN style="FONT-FAMILY: Arial, Helvetica, sans-serif">                                                       </SPAN> 

#include<stdio.h>
#include<string.h>
int main()
{
    int i,j,n,s1,s2,flag[10];
    while(~scanf("%d",&n))
    {
        for(i=1234;i<5000;i++)
        {
            memset(flag,0,sizeof(flag));
            /*flag保存每一位數字*/
            s1=i;
            s2=i*n;
            while(s1||s2)
            {
                if(!flag[s1%10])
                {
                    flag[s1%10]=1;
                    s1/=10;
                }
                else
                    break;
                if(!flag[s2%10])
                {
                    flag[s2%10]=1;
                    s2/=10;
                }
                else
                    break;
            }
            for(j=0;j<10;j++)
              if(!flag[j])
                  break;  /*判斷是否是10個各不相同的數字*/
            if(j==10&&i*n<=98765) /*如果數字各不相同*/
            {
                if(i<10000) /*除數是一個四位數,有前導0*/
                  printf("%d / 0%d = %d\n",i*n,i,n);
                else
                  printf("%d / %d = %d\n",i*n,i,n);
            }
        }
    }
                                                                                                                            2、最大乘積
輸入n個元素組成的序列s,你需要找出一個乘積罪的的連續子序列。如果這個罪的的乘積不是正數,輸出-1.1<=n<=18,-10<=Si<=10;
樣例輸入:
3
2 4 -3
5
2 5 -1 2 -1
樣例輸出:
8
20
分析:連續子序列有兩個要素:起點和終點,因此只需枚舉起點和終點即可。由於每個元素的絕對值不超過10,一共又不超過18個元素,最大可能的乘積不會超過10^18,可以用long long 存下。
[cpp]
#include<stdio.h>  
#include<string.h>  
const int inf=999999; 
int main() 

    long long a[20],s[20]; 
    long long i,j,n,max; 
    while(~scanf("%lld",&n)) 
    { 
        memset(s,0,sizeof(s)); 
        s[0]=1; 
        max=-inf; 
        for(i=1;i<=n;i++) 
        { 
            scanf("%lld",&a[i]); 
            s[i]=s[i-1]*a[i]; 
            /*s[i]表示從第一個數到第i個數的乘積*/ 
        } 
        for(i=1;i<=n;i++) /*子序列長度*/ 
        { 
            for(j=i;j<=n;j++) 
            { 
                if(s[j]/s[j-i]>max) 
                  max=s[j]/s[j-i]; 
            } 
        } 
        if(max<0) 
           max=-1; 
        printf("%lld\n",max); 
    } 
    return 0; 

#include<stdio.h>
#include<string.h>
const int inf=999999;
int main()
{
    long long a[20],s[20];
    long long i,j,n,max;
    while(~scanf("%lld",&n))
    {
        memset(s,0,sizeof(s));
        s[0]=1;
        max=-inf;
        for(i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            s[i]=s[i-1]*a[i];
            /*s[i]表示從第一個數到第i個數的乘積*/
        }
        for(i=1;i<=n;i++) /*子序列長度*/
        {
            for(j=i;j<=n;j++)
            {
                if(s[j]/s[j-i]>max)
                  max=s[j]/s[j-i];
            }
        }
        if(max<0)
           max=-1;
        printf("%lld\n",max);
    }
    return 0;
}


 
                                              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]
#include<stdio.h>  
#include<string.h>  
struct integer 

    int X,Y; 
}a[10000]; 
int main() 

    int i,j,y,k,count; 
    while(~scanf("%d",&k)) 
    { 
        memset(a,0,sizeof(a)); 
        i=count=0; 
        for(y=k+1;y<=k*2;y++) 
        { 
            if(y*k%(y-k)==0) 
            { 
                count++; 
                a[i].X=y*k/(y-k); 
                a[i++].Y=y; 
            } 
        } 
        printf("%d\n",count); 
        for(j=0;j<i;j++) 
            printf("1/%d = 1/%d + 1/%d\n",k,a[j].X,a[j].Y); 
    } 
    return 0; 

#include<stdio.h>
#include<string.h>
struct integer
{
 int X,Y;
}a[10000];
int main()
{
 int i,j,y,k,count;
 while(~scanf("%d",&k))
 {
  memset(a,0,sizeof(a));
  i=count=0;
  for(y=k+1;y<=k*2;y++)
  {
   if(y*k%(y-k)==0)
   {
    count++;
    a[i].X=y*k/(y-k);
    a[i++].Y=y;
   }
  }
  printf("%d\n",count);
  for(j=0;j<i;j++)
   printf("1/%d = 1/%d + 1/%d\n",k,a[j].X,a[j].Y);
 }
 return 0;
}
                                                                                              4、雙基回文數
 如果一個正整數n至少在兩種不同的禁止下b1和b2下都是回文數(2<=b1,b2<=10),則稱n是雙基回文數(注意,回文數不能包含前導零)。輸入正整數S<10^6,輸出比S大的最小的雙基回文數。
樣例輸入:  1600000
樣例輸出:  1632995
分析:最自然的想法就是:從n+1開始依次判斷每個數是否為雙基回文數,而在判斷時枚舉所有可能的基數(2~10),一切都是那麼的“暴力”。令人有些意外的是:這樣做對於S<10^6這樣的“小規模數據”來說是足夠快的——雙基回文數太多太密了。
[cpp]
#include<stdio.h>  
int a[30]; 
int huiwen(int s[],int n) /*判斷是否回文*/ 

    int i; 
    for(i=0;i<=n/2;i++) 
    { 
        if(a[i]!=a[n-i]) 
        { 
            return 0; 
            break; 
        } 
    } 
    return 1; 

int converse(int n,int k) /*把十進制的n轉化為k進制*/ 

    int flag=0,i,j=0; 
    while(n) 
    { 
        a[j++]=n%k; 
        n/=k; 
    } 
    if(huiwen(a,j-1)) 
      flag=1;  
    if(flag)  /*n在k進制下是回文數*/ 
      return 1; 
    else 
      return 0; 

int main() 

    int i,j,k,n,cnt; 
    while(~scanf("%d",&n)) 
    { 
        for(j=n+1;;j++) 
        { 
            int p=0; 
            for(i=2,cnt=0;i<=10;i++) 
            { 
                if(converse(j,i)) 
                   cnt++;  /*記錄回文次數*/ 
                if(cnt>=2)  /*是雙基回文數*/ 
                { 
                    p=1; 
                    break; 
                } 
            } 
            if(p) 
            { 
                printf("%d\n",j); 
                break; 
            } 
        } 
    } 
    return 0; 

#include<stdio.h>
int a[30];
int huiwen(int s[],int n) /*判斷是否回文*/
{
    int i;
    for(i=0;i<=n/2;i++)
    {
        if(a[i]!=a[n-i])
        {
            return 0;
            break;
        }
    }
    return 1;
}
int converse(int n,int k) /*把十進制的n轉化為k進制*/
{
    int flag=0,i,j=0;
    while(n)
    {
        a[j++]=n%k;
        n/=k;
    }
    if(huiwen(a,j-1))
      flag=1;
    if(flag)  /*n在k進制下是回文數*/
      return 1;
    else
      return 0;
}
int main()
{
    int i,j,k,n,cnt;
    while(~scanf("%d",&n))
    {
        for(j=n+1;;j++)
        {
            int p=0;
            for(i=2,cnt=0;i<=10;i++)
            {
                if(converse(j,i))
                   cnt++;  /*記錄回文次數*/
                if(cnt>=2)  /*是雙基回文數*/
                {
                    p=1;
                    break;
                }
            }
            if(p)
            {
                printf("%d\n",j);
                break;
            }
        }
    }
    return 0;
}


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved