2022/10/14拓展班上机课题解

7-3 位运算

在这里插入图片描述
默认理解十进制数和二进制数的转换。

三种位运算符&,|,^

  • 对于&,只有1&1为1,其余都为0。
  • 对于|,只有0|0为0,其余都为1。
  • 对于^,相同为0,不同为1,比如1^1=0,1^0=1。

分析我们要达成的三种效果

  • 因为1&0=0,0&0=0,所以对要变的第k位&0可以达到置0的效果;对于不需要变的位$1:1$1=1,0$1=0。
  • 因为0|1=1,1|1=1,所以对要变的第k位|1可以达到置1的效果;对于不需要变的位|0:0|0=0,1|0=1。
  • 因为 0^1=1 1^1=0,所以只要把要变的第k位^1即可达到取反的效果;对于不需要变的位^0:0^0=0,1^0=1。
#include<stdio.h>
int main(){
    //1&0=0,0&0=0,所以&0可以置0,1&1=1,0%1=0
    //1|1=1,0|1=1,所以|1可以置1,0|0=0,1|0=1
    //1^1=0,0^1=1,所以^1可以取反,1^0=1,0^0=0
    int x;
    scanf("%d",&x);
    int ord,k;
    int tmp,rev;//tmp临时变量,rev作用的数
    while(scanf("%d %d",&ord,&k)!=EOF){
        switch(ord){
            case 1://置0
                //k=2,11111011
                //1=00000001 1<<2=00000100
                //00000100^11111111(-1)=11111011
                tmp = -1;
                rev = 1;
                rev <<= k;
                rev ^= tmp;
                x &= rev;
                break;
            case 2://置1
                //k=2 00000100
                rev = 1;
                rev <<= k;
                x |= rev;
                break;
            case 3:
                //k=2 00000100
                rev = 1;
                rev <<= k;
                x ^= rev;
                break;
            default:
                break;
        }
    }
    printf("%d",x);
}

过程中有同学分享取反的位运算符~,表扬!

x=x&~(1<<k)//置0
x=x|(1<<k)//置1
x=x^(1<<k)//取反

7-2 二分法求多项式单根

在这里插入图片描述
上一节拓展上机课讲完后才知道很多同学不清楚全局变量,这里补充一下:

  • 定义在函数内部的变量称为局部变量(Local Variable),它的作用域仅限于函数内部, 离开该函数后就是无效的,再使用就会报错。
    • (这一小点涉及函数的知识,未学习函数的同学可先跳过) 形参变量、在函数体内定义的变量都是局部变量。实参给形参传值的过程也就是给局部变量赋值的过程。
  • 在所有函数外部定义的变量称为全局变量(Global Variable),它的作用域默认是整个程序。
    • 当全局变量和局部变量同名时,在局部范围内全局变量被“屏蔽”,不再起作用。或者说,变量的使用遵循就近原则,如果在当前作用域中存在同名变量,就不会向更大的作用域中去寻找变量。

接着说一下二分的思想:

  • 二分就是一分为二。简单来说二分就是在一个序列中,通过不断的二分,进而不断地缩小范围去寻找满足我们条件的解。
  • 有兴趣的同学可以了解学习一下二分查找。

最后说一下本题的思路:

  • 初等数学中我们学习过函数,对于一个函数f(x),当出现f(x0)=0,即x0为函数f(x)的一个根,当然这个题目也有说明。且题目保证多项式在给定区间内存在唯一单根。
  • 也就是说这道题就是让我们在给定的区间[l,r]中找到一个x0,满足f(x0)=0。
  • 所以我们将区间一分为二, m i d = l + r 2 mid=\frac{l+r}{2} mid=2l+r。判断一下mid是不是我们要找的根,如果不是,就对根所在的区间进行缩小。
  • 根据题目给出的:
    • 如果 f ( ( a + b ) / 2 ) 与 f ( a ) 同 号 , 则 说 明 根 在 区 间 [ ( a + b ) 2 , b ] f((a+b)/2)与f(a)同号,则说明根在区间[\frac{(a+b)}{2},b] f((a+b)/2)f(a)[2(a+b),b]
    • 如果 f ( ( a + b ) / 2 ) 与 f ( b ) 同 号 , 则 说 明 根 在 区 间 [ a , ( a + b ) 2 ] f((a+b)/2)与f(b)同号,则说明根在区间[a,\frac{(a+b)}{2}] f((a+b)/2)f(b)[a,2(a+b)]

      ~~~~~       确定根所在的新区间(缩小了一半)

  • 重复以上步骤直到找到根。
  • (特判)这题还要注意一下题目说的:
    精确到小数点后2位和检查区间长度,如果小于给定阈值,则停止
#include<stdio.h>
double a3, a2, a1, a0;
double func(double x){//计算f(x)
    return a3*x*x*x+a2*x*x+a1*x+a0;    
}
int main(){
    //区间范围大于等于0.01的时候要取精确值,小于0.01的时候可以取粗略值(a+b)/2
    scanf("%lf %lf %lf %lf",&a3, &a2, &a1, &a0);
    
    double l, r;
    scanf("%lf %lf",&l,&r);//输入区间

    while(r-l>=0.01){
        double mid = (l+r)/2;
        //计算精确根
        if(!func(mid)) {
            printf("%.2f",mid);
            break;
        }
        else if(func(l)*func(mid)<0)
            r = mid;
        else l = mid;
        
    }
    if(r-l<0.01) printf("%.2f",(l+r)/2);
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值