CF1110C Meaningless Operations(构造题)

这可能是我打那么多次CF比赛时,做出来的最难的一道题了……而且这题也是个绝世好题……

题目链接:CF原网  洛谷

题目大意:$q$ 组询问,每次给定 $a$ 询问 $gcd(a&b,aoplus b)$ 的最大值,其中 $1le b<a$。规定 $gcd(a,0)=a$。


真的是神仙题……

打几个表,我们发现如果 $a$ 的二进制表示中含有 $0$,比如 $100101100...$,也就是说不能表示成 $2^k-1$,那么他的答案就是所有 $2^k-1$ 中比 $a$ 大的最小的一个。

(虽然这个规律不是我打表找到的,是自己推出来的)

为什么呢?如果我们令 $b$ 为 $a$ 的位取反,那么 $a&b=0,aoplus b=2^k-1$。所以答案就是 $2^k-1$。可以证明答案不可能超过 $2^k-1$。

复杂度 $O(log a)$。

那么 $a=2^k-1=(11111...)_2$ 怎么办呢?似乎大多数人都是暴力打出一个表然后直接调用的……

我的做法是:我们发现对于一个 $1le b<a$,有 $a&b=b,aoplus b=a-b$。

那么 $gcd(a&b,aoplus b)=gcd(b,a-b)=gcd(a,b)$!!!

$gcd(a,b)$ 的最大值?就是 $a$ 的最大因数(不包括 $a$ 自己)。

总复杂度 $O(qsqrt{a})$。

代码:

#include<bits/stdc++.h>
using namespace std;
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
    char ch=getchar();int x=0,f=0;
    while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return f?-x:x;
}
int q,n;
int main(){
    q=read();
    while(q--){
        n=read();
        int c=1;
        while(c<=n) c<<=1;
        if(n!=c-1) printf("%d
",c-1);
        else{
            bool flag=false;
            for(int i=2;i*i<=n;i++)
                if(n%i==0){printf("%d
",n/i);flag=true;break;}
            if(!flag) printf("1
");
        } 
    }
}
View Code
原文地址:https://www.cnblogs.com/1000Suns/p/10355991.html