CF Week12 作业 解题报告

611A

题意:给出1<=a<=b<=10^18,求区间[a,b]内有多少个数二进制下只有一个0

solution:2^61>10^18,所以区间内的数最多二进制下61位,位数从2位枚举到61位,每次把非最高位变成0其余为1,将这个数存到数组里

 1 #include<iostream>
 2 #include<cstdio>
 3 #define LL long long
 4 using namespace std;
 5 LL A[200000],n;
 6 int main(){
 7     LL a,b; cin>>a>>b;
 8     int i,j;
 9     for (i=2;i<=61;i++){
10         LL num=((LL)1<<(LL)i)-1;//位运算注意转long long 
11         for (j=i-2;j>=0;j--){//不能把最高位变成0 
12             A[++n]=num^(LL)((LL)1<<(LL)j);//同上 
13         }
14     }
15     int pos1=0,pos2=0;
16     for (i=1;i<=n;i++){
17         if (a<=A[i]&&!pos1) pos1=i;
18         if (b>=A[i]) pos2=i; 
19     }
20     cout<<pos2-pos1+1;
21 }

633A

题意:a,b<=100两种面值硬币,求能否拼成c<=10000

其实就是求ax+by=c能否求出a,b都为自然数的一组解,用扩欧求出来任意一组,然后运用公式(x+k*b/gcd(a,b),y-k*a/gcd(a,b)),k取任意整数判断

#include<iostream>
using namespace std;
void Gcd(int a,int b,int &d,int &x,int &y){
    if (!b){
        d=a; x=1; y=0; return;
    }
    Gcd(b,a%b,d,y,x); y-=x*(a/b);
}
int main(){
    int a,b,c,gcd,x,y; cin>>a>>b>>c;
    Gcd(a,b,gcd,x,y);
    if (c%gcd!=0){cout<<"No"; return 0;}//肯定不会有整数解 
    x*=c/gcd; y*=c/gcd;//ax+by=c的解 
    
    if (x>=0&&y>=0){cout<<"Yes"; return 0;}
    //两个解都不为负 
    int b1=b/gcd,a1=a/gcd;
    if (x>0) swap(x,y),swap(a1,b1);
    //将x置为负解 
    int k=(-x)/b1; if ((-x)%b1!=0) k++;
    //求出使x+k*b/gcd(a,b)>=0的最小k 
    if (y-k*a1<0) cout<<"No";
    //此时另一个解y-k*a/gcd(a,b) 
    else cout<<"Yes";
}

猜你喜欢

转载自www.cnblogs.com/Pedestrian6/p/9107430.html