您的位置:首页 > 其它

经典小算法小方法总结

2015-12-04 16:40 253 查看
# 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
f93a
;

    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;//最小公倍数

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: