数学与位运算相关题

1.非波那切数列(青蛙跳台阶1个、2个)(矩形覆盖)

跳台阶题目
矩形覆盖题目
----->递归(时间复杂度过高O(2^n)),
------>动态规划:f(n)=f(n-1)+f(n-2); while(n–>2)时;f(n)=f(n-1)+f(n-2)即b=b+a;f(n-1)保存即a=b-a;

注意while中>2是关键;这是由a和b的初始化决定的;

2.青蛙跳台阶,一次跳1个、2个、…n个;

题目
—>f(n)=f(n-1)+f(n-2)+…f(2)+f(1)+f(0); f(0)即一次跳n个;

//初始化f(0)=1; f(1)=1;
while(number-->1)
b=b+a;
a=b;
//或
sum=1;
while(number-->1)
sum*=2;

对于这样的问题,先根据前几项找通式或规律;再写代码;

3.数值的整数次方

题目
----->对次方正负分类讨论

注意是base *= onebase;
int/double为int ; 应为double/double;

4数组中只出现一次的数字:

题目

----->注意&^比==优先级低;所以要在 while((index&xor1)==0)里面加上括号;

考点:& 、^、<<运算;相同两个数异火为0;
while((index&xor1)==0) index<<=1;求最右边1的位置; 即非0时退出;

扫描二维码关注公众号,回复: 11370064 查看本文章

5.二进制中1的个数

题目

n=n&(n-1); n-1即从右往左数到第一个1开始取反,在与n进行&运算,即将去除原数的最右边的1及后面的;

-1的二进制为32;int的二进制共32位

6.不用加减乘除做加法(^&<<):

题目
---->先异或(使用temp变量保存),在求进位(与与左移),更新结果,只要进位不为空;

do{}while;

求两数之差:依次使用的运算符(&^^|<<):------>1.调用加法(a的负数:Add(~a,1));
2.只要b不为空,先求相同位,两数去除相同位,再与|运算,被减数右移;
异或减

7.判断点p是否在三角形中

内角和等于360度(误差大)或求面积(交叉向量求面积(一定为正值):定义一个结构体,
s=(ab-> * bc->)/2.0=(AB.xBC.y-AB.yBC.x)/2.0)之和,判断时要用&&; ABC、ABP、BCP、ACP;

struct point{
    int x;
    int y;
    point(int i,int j):x(i),y(j){};
};
double area(point A,point B,point C)
	{
	double x1=A.x-B.x;
    double y1=A.y-B.y;
    double x2=B.x-C.x;
    double y2=B.y-C.y;
    return (x1*y2-x2*y1)/2.0;
    }
  • p点一定在AB边下边,AC边右边,BC边左边;一个Vector3类(构造函数、重载-函数、Dot函数、Cross函数);PointinTriangle函数,SameSide函数();
    三角形

8.丑数(只包含2、3、5因子的树)穷举法:

题目
初始化三个指针p1、p2、p3的索引为0;分别指向*2、*3、*5的索引位置;每次将res[pi]*pi中最小的赋值;

  • 质数:暴力法j<i(改为sqrt(i)):i%j==0,返回false;
  • 质数:筛法:初始化arr(1000,1);如果arr[i]==1:计算j=i;ji<1000;arr[ji]=0;

min(a,b);

9.排序数组和为s且乘积最小的两个数:

题目
—>双指针法:i指向开始,j指向结束;和相同两数相差越远其积越小;

10.游戏:n个孩子,每次数m次,选出的去除,直到剩余最后一个:

题目
1.删除法:.(注意每个变量都要初始化,不一定默认为0)使用vec保存0~n-1的值;每喊m次从vector中erase一个元素;

int LastRemaining_Solution(int n, int m)
    {
        if(n<1|| m<1)
            return -1;
        vector<int> res;
        for(int i=0;i<n;i++)
            res.push_back(i);
        int i=0;
        while(res.size()>1)
        {
            i=(i+m-1)%res.size();
            res.erase(res.begin()+i);
        }
        return res[0];
    }

2.归纳法:每次加m,分别对n、n-1、n-2、…2、1进行取余数;

int LastRemaining_Solution(int n, int m)
    {
        if(n<1 || m<1)
            return -1;
        int s=0;
        for(int i=1;i<n+1;i++)
            s=(s+m)%i;
        return s;
    }

3.暴力法:虽然不好,但是也可以锻炼思维;

class Solution {
public:
    int LastRemaining_Solution(int n, int m)
    {
        if(n<1 || m<1)
            return -1;
        vector<int> child(n,0);
        int i=0;
        int k=0;
        while(i<n-1)
        {
            int j=0;
            while(j<m-1)
            {
                if(child[k]==0)
                {
                    j++;
                }
                k=(k+1)%n;
            }
            while(child[k]==1)
                k=(k+1)%n;
            child[k]=1;
            i++;
        }
        for(i=0;i<n;i++)
            if(child[i]==0)
                return i;
    }
};

11.减绳子(各段乘最大):

题目
1.类推法:趋于中间的两数乘最大,先处理number<=3的,在使用vec初始化,每次入(v[j]*v[j-i]);

2.数学法:先处理number<=3情况,再处理number>5时: number%3取余数分类讨论;

取幂次方pow(3,n)

猜你喜欢

转载自blog.csdn.net/qq_42698422/article/details/106823054