1、计算二进制数中1的个数:
int num=0;
while(v)
{
v&=(v-1);
num++;
}
2、2.4. 1的数目
输入n,写出1到n的所有1的个数
#include<iostream>
using namespace std;
long long Sums(long long n)
{
long long icount=0;
long long ifactor=1;
long long ilowernum=0;
long long icurrnum=0;
long long ihighernum=0;
while(n/ifactor!=0)//从个位开始,像高位看
{
ilowernum=n-(n/ifactor)*ifactor;//低位数
icurrnum=(n/ifactor)%10;//当前位
ihighernum=n/(ifactor*10);//高位数
switch(icurrnum)
{
case 0://当前位是0
icount+=ihighernum*ifactor;
break;
case 1://当前位是1
icount+=ihighernum*ifactor+ilowernum+1;//高位和低位
break;
default://当前位是其他
icount+=(ihighernum+1)*ifactor;
break;
}
ifactor*=10;
}
return icount;
}
int main()
{
long long n;
cin>>n;
cout<<Sums(n)<<endl;
return 0;
}
2.5 寻找最大的K个数
思路:堆排序。一遍搜索,找出K个最大的数,遇到比最小的大的插入,把最小的挤出去。最小堆。
2.6 精确表达浮点数
2.7 最大公约数问题
1、f(x,y)=f(y,x%y)
eg: f(42,30)=f(30,12)=f(12,6)=f(6,0)=6
2、f(x,y)=f(x-y,y)
3、x、y都是偶数,f(x,y)=2*f(x/2,y/2)
x偶,y奇数,f(x,y)=f(x/2,y)
x奇数,y偶,f(x,y)=f(x,y/2)
x,y均为奇数,f(x,y)=f(y,x-y)
2.8 找出符合条件的整数,没看懂。。。
任意给定一个正整数N,求一个最小的正整数M(M>1),使得N*M的十进制表示形式里只含有1和0
#include<iostream>
#include<cstring>
using namespace std;
int find_M(int N)
{
//边界条件
if(N==1)
return 1;
//初始化余数数组
int *A=new int[N];//记录已有的余数 ,A[i]表示对N的余数为i的最小满足条件的数值
int *B=new int[N]; //记录更新的余数
memset(A,-1,N*sizeof(int));
A[1]=1;
//寻找过程
int factor=10;//10,100,1000,.....
bool not_found=true;
while(not_found)
{
memset(B,-1,N*sizeof(int));
int x=factor%N;//高位数值对N的余数
cout<<"x "<<x<<" ";
cout<<"A[X]"<<A[x]<<endl;
//高位数值+0的情况
if(A[x]==-1)
{
B[x]=factor;
cout<<"B[]X"<<B[x]<<endl;
if(x==0)
break;
}
//高位数值+低位正整数的情况
for(int i=1;i<N;i++)//遍历每个可能的余数
{
if(A[i]==-1)
continue;
int new_x=(x+i)%N;//计算出的余数
cout<<"new_x "<<new_x<<" x "<<x<<" i "<<i<<endl;
if(A[new_x]==-1&&B[new_x]==-1)//如果是一个新的余数,保存
{
B[new_x]=factor+A[i];
cout<<"new_x "<<new_x<<" "<<B[new_x]<<endl;
if(new_x==0)//刚好找到的新的余数是0
{
not_found=false;
break;
}
}
}
factor*=10;
for(int i=0;i<N;i++)
{
if(A[i]==-1&&B[i]!=-1)
A[i]=B[i];
}
}
int result=B[0];
delete[]A;
delete[]B;
return result;
}
int main()
{
int N;
while(true)
{
cout<<"N:";
cin>>N;
if(N<1)
break;
cout<<"M:"<<find_M(N)/N<<endl;
cout<<"正整数为:"<<find_M(N)/N*N<<endl;
}
return 0;
}
测试过程,如输入6
N=6的计算过程
factor=10
x=4 A[x]=-1 所以,B[X]=10
for循环
i=1,new_x=5;
B[5]=11
A[5]=11
facotr=100;
A[4]=B[4]=10;
B清空
x=100%6=4
for循环中:
new_x=(4+4)%6=2;
B[2]=100+10=110;
new_x=(4+5)%6=3;
B[3]=100+11=111
factor=1000
A[2]=B[2]=110
B清空
x=1000%6=4
for循环
new_x=(4+2)%6=0;
B[0]=1110;
直接跳出
2.10 寻找数组中最大值和最小值
分治思想
(int max,int min)Search(int arr[],int b,int e)
{
if(e-b<=1)//不是最后一个数
{
if(arr[b]<arr[e])
return (arr[e],arr[b]);
else
return (arr[b],arr[e]);
}
int maxL,minL,maxR,minR,minV,maxV;
(maxL,minL)=Search(arr,b,b+(e-b)/2);
(maxR,minR)=Search(arr,b+(e-b)/2+1,e);
if(maxL>maxR)
maxV=maxL;
else
maxV=maxR;
if(minL<minR)
minV=minL;
else
minV=minR;
return (maxV,minV);
}
一共需要比较 1.5N-2次。
2.12快速寻找满足条件的两个数,两个数的和等于一个给定的值
首先,排序,时间复杂度:Nlog2N.然后两个指针,前一个后一个,两数之和<x,i++,>x,j–.
(int i,int j) find(int arr[],int n,int x)
{
int i=0,j=n--;
while(i<j)
{
if(arr[i]+arr[j]==x)
return (i,j);
else if(arr[i]+arr[j]<x)
i++;
else
j--;
}
return (-1,-1);
}
2.13子数组的最大乘积,N-1个数的最大乘积
设N个数的乘积是P
若p==0,则至少有一个0,把0删去,讨论剩下所有数乘积的正负:若为负数,则得0,若为正数,则为该正数
若p<0,则负数个数是奇数,除去一个负数,则是正数,一定最大。
若p>0,如果存在正数,去掉一个最小的正数,否则去掉一个绝对值最大的负数,反正都是去掉一个最小的数。
2.14 和最大的连续子数组
从后往前遍历
int max(int x,int y)
{
return (x>y)?x:y;
}
int maxSum(int *A,int n)
{
nstart=A[n-1];
nall=A[n-1];
for(i=n-2;i>=0;i--)
{
nstart=max(A[i],nall+A[i]);
nall=max(nstart,nall);
}
}