Codeforces Round #554 (Div. 2)做题记录

Codeforces Round #554 (Div. 2)做题记录

这是rain__star小菜鸡写的第一篇博客。rain__star是一位新入坑的算法爱好者,崇尚数学,热衷于一切神秘或者神奇的事物。作为一位合格的菜鸟,最近突发奇想,希望写博客来记录自己做过的题,希望能具备越来越丰富深奥的知识,解决越来越艰深的问题。算法之路漫漫,吾辈当上下求索!
水平有限,只做出ABC三题,先记录一下。

A http://codeforces.com/contest/1152/problem/A

水题不谈。

B http://codeforces.com/contest/1152/problem/B

这一题要求寻求一种方法使得对x进行不大于40次ab操作后,变成 2 m 1 2^m-1 的形式。
事实上根据样例一我们就可以发现:对于39即100111,先不考虑低位的连续的1,找到这之后连续0的最高位,即第五位,将39对 2 5 1 2^5-1 做异或操作,得到111000,之后+1,得到111001,再重复一次上述步骤,得到111110–》111111,我们发现总能通过4步将某一连续0的区间变为连续1.题目x的不超过1e6,即位数不超过20,即连续0区间个数不超过10,于是总能在40步之内完成要求。
AC代码:
#include
using namespace std;
bool f(int x){
while(x){
if(!(x&1))return false;
x>>=1;
}
return true;
}
int f1(int x){
int res=1,k=1;
while(k&x)k<<=1,res++;
if(k>x)return 0;
while(!(k&x))k<<=1,res++;
return res;
}
int ans[50],cnt=0;
int main(){
int n; cin>>n;
int t=0;
if(f(n)){
cout<<0; return 0;
}
while(1){
t++;
if(t%2){
ans[++cnt]=f1(n)-1;
n=((1<<(f1(n)-1))-1)^n;
if(f(n))break;
}
else{
n++;
if(f(n))break;
}
}
cout<<t<<endl;
for(int i=1;i<=cnt;i++)cout<<ans[i]<<" ";
}

C http://codeforces.com/contest/1152/problem/C

对于任意的a,b,我们要寻求a+k,b+k最小公倍数的最小值。我们知道a+k,b+k的最小公倍数=(a+k)(b+k)/gcd(a+k,b+k),于是我们只需要枚举a+k,b+k所有可能的公因子并且使k尽可能小即可。怎么确定这些公因子呢?事实上只需要寻找m使得a%mb%m,这时只需令 k=(m-a%m)%m,就得到(a+k)%m(b+k)%m0。而m的值很显然就是(abs(a-b))的所有因子!于是只需用o(根号(abs(a-b)) )的时间枚举即可。
AC代码:
#include
#include
using namespace std;
#define ll long long
ll gcd(ll x,ll y){
if(y
0)return x;
return gcd(y,x%y);
}
ll t2[100005],cnt=0;
int main(){
ll a,b;
cin>>a>>b;
ll t=abs(a-b);
ll ans=0,mins=a
b/gcd(a,b);
for(ll i=1;i<=sqrt(t);i++){
if(t%i0){
ll k=(i-a%i)%i;
ll tmp=(a+k)*(b+k)/gcd(a+k,b+k);
if(tmp<mins){
mins=tmp; ans=k;
}
else if(tmp
mins)ans=min(ans,k);
ll j=t/i; k=(j-a%j)%j;
tmp=(a+k)*(b+k)/gcd(a+k,b+k);
if(tmp<mins){
mins=tmp; ans=k;
}
else if(tmp==mins)ans=min(ans,k);
}
}
cout<<ans;
}

DEF1F2

不会。。。
(完)

猜你喜欢

转载自blog.csdn.net/rain__star/article/details/89510755