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"; }