經典小算法小方法總結

# include<stdio.h>

# include<string.h>

 

char flag[10];

char backup[10];

 

int check(int n)

{

    do {

        flag[n % 10]++;

    } while(n /= 10);

    if(flag[0] != 0) {

        return 1;        //判斷組成n的數字是否有重複

}

/*

for(i=0;i<4;i++)

        for(j=i+1;j<5;++j)

            if(num[i]==num[j])return 0;

                  //也能判斷但是較前者而言,顯得老套不精妙,

*/

    for(int i = 1; i < 10; i++) {

        if(flag[i] > 1) {

            return 1;

        }

    }

    return 0;

}

 

int checkAll(void)

{

    for(int i = 1; i < 10; i++) {

        if(flag[i] != 1) {

            return 1;

        }

    }

    return 0;

}

 

int main(void)

{

    int num;

    int count = 0;

    scanf("%d", &num);

    int left, right, up, down;

    for(left = 1; left < num; left++) {

        memset(flag, 0, 10);

        if(check(left)) {

            continue;

        }

        memcpy(backup, flag, 10);

        for(down = 1; down < 100000; down++){

            memcpy(flag, backup, 10);

            up = (num - left) * down;

            if(check(down) || check(up)) {

                continue;

            }

            if(! checkAll()) {

                //printf("%d = %d + %d /%d\n", num, left, up, down);

                count++;

            }

        }

    }

    printf("%d\n", count);

}

 

 

#include<iostream>

#define max 100000

using namespacestd;

int judge(intn,int m){

    int num[5],i,j,p=n;

    i=0;

    while(p)

    {

        num[i++]=p%10;

        p/=10;

    }

    for(i=0;i<4;i++)

        for(j=i+1;j<5;++j)

            if(num[i]==num[j]) return 0;

    p=n*m;

   if(p/max) return 0;

    i=4;

    while(p)

    {

        if(p%10!=num[i--])return 0;

        p/=10;

    }

    return 1;

}

int main()

{

    int i,j;

    for(i=10000;i<max;++i)

        for(j=2;j<10;j++)

            if(judge(i,j))cout<<i<<endl;

    getchar();getchar();

    return 0;

}

 

 

 

Adjacent  Bit  Counts

Description

For astring of n bits x1, x2, x3, …, xn,  theadjacent bit count of the string  isgiven by     fun(x) = x1*x2+ x2*x3 + x3*x 4 + … + xn-1*xn
which counts the number of times a 1 bit is adjacent to another 1 bit. Forexample:  

     Fun(011101101) = 3

     Fun(111101101) = 4

     Fun (010101010) = 0

Write a program which takes asinput integers n and p and returns the number of bit stringsx of n bits (out of 2ⁿ) that satisfy  Fun(x)= p.

 

Forexample, for 5 bit strings, there are 6 ways of getting fun(x) = 2:

11100,01110, 00111, 10111, 11101, 11011

 

Standard input

Onthe first line of the input is a single positive integer k, telling the numberof test cases to follow. 1 ≤ k ≤ 10  Eachcase is a single line that contains  adecimal integer giving the number (n) of bits in the bit strings, followed by asingle space, followed by a decimal integer (p) giving the desired adjacent bitcount. 1 ≤ n , p ≤ 100

Standard  output

For each test case, output a linewith the number of n-bit strings with adjacent bit count equal to p.

 
Sample  Input                 Sample  Output

2

5 2                                6

20 8                               63426


#include<stdio.h>

#include<math.h>

int tempmax=0;

int sumfun(int *ss,int bits)

{

   int i,temp=0;

   for(i=0;i<=bits-2;i++)

    {

       temp+=ss[i]*ss[i+1];

    }

   return temp;

}

int fun1(int n,int sum,int bits)

{

   int ss[100]={0};

   int t=n,i=0;

    while(t>0)

    {

        ss[i]=t%2;

        t=(t-ss[i])/2;

         i++;

    }                   //十進制轉換爲二進制

   if(sumfun(ss,bits)==sum)

   return 1;

   else return 0;

 

}

void fun(int bits,int sum)

{

   int max=1;

   int i,j,k;

    for(i=0;i<bits;i++)max=2*max;

    for(i=0;i<max;i++)           //代替建立建立層數爲bits的子集樹

     if(fun1(i,sum,bits))

       tempmax++;

}

int main()

{

   int n;

   int ans[10];

   scanf("%d",&n);

   int i,j,k;

   int bits,sum;

   for(i=0;i<n;i++)

    {

       tempmax=0;

       scanf("%d %d",&bits,&sum);

       fun(bits,sum);

       ans[i]=tempmax;

    }

   for(i=0;i<n;i++)

    {

       printf("%d\n",ans[i]);

    }

   return 0;

}

對於vc(一般軟件都如此)

char

unsigned char

short

unsigned short

int

unsigned int

Long long

unsigned long long

 

兩個數交換值:

a=a+b;

b=a-b;

a=a-b;

或者:

a=aΛb;//按位異或操作

b=aΛb;

a=aΛb;

  

求float型變量a的小數部分:整數部分爲  a-(int)a;

求int a能否被intb 整除:a/b*b==a 成立則能否則不能

 

關於對數組下標的利用可以非常的精妙,二維數組的應用,數據庫的建立

 

 

 

統計整數二進制表示中1的個數

Craneposted @ 2010年5月07日 23:51 in Programing with tags 位運算c算法二進制 , 4927 閱讀

這是一個很有意思的問題,也是在面試中最容易被問到的問題之一。這個問題有個正式的名字叫Hamming_weight,而且wikipedia上也提供了很好的位運算解決的方法,這個下面也會提到。

解決這個問題的第一想法是一位一位的觀察,判斷是否爲1,是則計數器加一,否則跳到下一位,於是很容易有這樣的程序。

?

1

2

3

4

5

6

7

8

9

10

inttest(intn)

{

    intcount=0;

    while(n != 0){

        if(n%2 ==1)

            count++;

        n /= 2;

    }

    returncount;

}

 

或者和其等價的位運算版本:

?

1

2

3

4

5

6

7

8

9

inttest(intn)

{

    intcount=0;

    while(n != 0){

        count += n&1;

        n >>= 1;

    }

    returncount;

}

 

這樣的方法複雜度爲二進制的位數,即,於是可是想一下,有沒有隻與二進制中1的位數相關的算法呢。

可以考慮每次找到從最低位開始遇到的第一個1,計數,再把它清零,清零的位運算操作是與一個零,但是在有1的這一位與零的操作要同時不影響未統計過的位數和已經統計過的位數,於是可以有這樣一個操作n&(n-1) ,這個操作對比當前操作位高的位沒有影響,對低位則完全清零。拿6(110)來做例子,第一次 110&101=100,這次操作成功的把從低位起第一個1消掉了,同時計數器加1,第二次100&011=000,同理又統計了高位的一個1,此時n已變爲0,不需要再繼續了,於是110中有2個1。

代碼如下:

?

1

2

3

4

5

6

7

8

9

inttest(intn)

{

    intcount=0;

    while(n != 0){

        n &= n-1;

        count ++;

    }

    returncount;

}

 

這幾個方法雖然也用到了位運算,但是並沒有體現其神奇之處,下面這個版本則彰顯位運算的強大能力,若不告訴這個函數的功能,一般一眼看上去是想不到這是做什麼的,這也是wikipedia上給出的計算hamming_weight方法。

?

1

2

3

4

5

6

7

8

9

10

inttest(intn)

{

    n = (n&0x55555555) + ((n>>1)&0x55555555);

    n = (n&0x33333333) + ((n>>2)&0x33333333);

    n = (n&0x0f0f0f0f) + ((n>>4)&0x0f0f0f0f);

    n = (n&0x00ff00ff) + ((n>>8)&0x00ff00ff);

    n = (n&0x0000ffff) + ((n>>16)&0x0000ffff);

 

    returnn;

}

 

沒有循環,5個位運算語句,一次搞定。

比如這個例子,143的二進制表示是10001111,這裏只有8位,高位的0怎麼進行與的位運算也是0,所以只考慮低位的運算,按照這個算法走一次

+---+---+---+---+---+---+---+---+
| 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |  <---143
+---+---+---+---+---+---+---+---+
|  0 1 |  0 0  |  10  | 1 0  |   <---第一次運算後
+-------+-------+-------+-------+
|    0 0 0 1    |   0 1 0 0    |   <---第二次運算後
+---------------+---------------+
|        0 0 0 0 0 1 0 1        |  <---第三次運算後,得數爲5
+-------------------------------+

這裏運用了分治的思想,先計算每對相鄰的2位中有幾個1,再計算每相鄰的4位中有幾個1,下來8位,16位,32位,因爲2^5=32,所以對於32位的機器,5條位運算語句就夠了。

像這裏第二行第一個格子中,01就表示前兩位有1個1,00表示下來的兩位中沒有1,其實同理。再下來01+00=0001表示前四位中有1個1,同樣的10+10=0100表示低四位中有4個1,最後一步0001+0100=00000101表示整個8位中有5個1。

 

超大數字的處理:

在做題的時候會遇到一些比較大的數字,比如1000位(十進制)的數字,或者是題目沒有明確指出他是多少位的,這時候不能相當然的認爲用int。

處理這樣的數字基本方法就是用字符數組存儲,然後再於字符‘0’做差得到原本值。

以下是兩個例子:

求兩數之和:

#include<stdio.h>

#include<string.h>

int main()

{

   char sa[1001],sb[1001];

       intlen_a,len_b,line,i,j,len;

       charans[20][3][1002];

       scanf("%d",&line);

       for(i=0;i<line;i++)

       {

              int a[1001]={0},b[1001]={0};

              scanf("%s",sa);

              scanf("%s",sb);

              strcpy(ans[i][0],sa);

              strcpy(ans[i][1],sb);

              len_a=strlen(sa);

              len_b=strlen(sb);

              for(j=len_a-1;j>=0;j--)a[len_a-1-j]=sa[j]-'0';

              for(j=len_b-1;j>=0;j--)b[len_b-1-j]=sb[j]-'0';

       len=len_a>len_b?len_a:len_b;

              for(j=0;j<len;j++)

              {

                     a[j]+=b[j];

                     a[j+1]+=a[j]/10;

                     a[j]=a[j]%10;

              }  

              if(a[len])

              {

                    

                     for(j=len;j>=0;j--)ans[i][2][len-j]=a[j]+'0';

                     ans[i][2][len+1]='\0';

              }

              else

              {

                     for(j=len-1;j>=0;j--)ans[i][2][len-1-j]=a[j]+'0';

           ans[i][2][len]='\0';

              }

       }

   for(i=0;i<line;i++)

       {

              printf("Case %d:\n",i+1);

              printf("%s + %s =%s\n",ans[i][0],ans[i][1],ans[i][2]);

              if(i!=(line-1))printf("\n");

       }

       return0;

}

求數值的各位數字之和直到小於10:

#include <stdio.h>

#include <stdlib.h>

#include<string.h>

int fun(int a)

{

       intsum=0;

       while(a)

       {

              sum+=a%10;

              a/=10;

       }

       returnsum;

}

int main()

{

       charss[1000];

       intlen,i,sum;

       while(scanf("%s",ss),*ss-'0')

       {

              sum=0;

              len=strlen(ss);

              for(i=0;i<len;i++)sum+=(ss[i]-'0');

              while(sum>=10)sum=fun(sum);

              printf("%d\n",sum);

       }

  return 0;

}

 

求最大公約數,最小公倍數:

int GDB(int a,int b)//最大公約數

{

   int t;

if(a<b)

{

    t=a;

    a=b;

    b=t;

}

While(b)

{

    t=a%b;

    a=b;

    b=t

}

return a;

}

LCM(a,b)=a/GDB(a,b)*b;//最小公倍數

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章