1. 程式人生 > >CF1110C Meaningless Operations(思想題)

CF1110C Meaningless Operations(思想題)

lap tps 可能 怎麽辦 org c++ 調用 != 復雜度

這可能是我打那麽多次CF比賽時,做出來的最難的一道題了……而且這題也是個絕世好題……

題目鏈接:CF原網 洛谷

題目大意:$q$ 組詢問,每次給定 $a$ 詢問 $\gcd(a\&b,a\oplus b)$ 的最大值,其中 $1\le b<a$。規定 $\gcd(a,0)=a$。


真的是神仙題……

打幾個表,我們發現如果 $a$ 的二進制表示中含有 $0$,比如 $100101100...$,也就是說不能表示成 $2^k-1$,那麽他的答案就是所有 $2^k-1$ 中比 $a$ 大的最小的一個。

(雖然這個規律不是我打表找到的,是自己推出來的)

為什麽呢?如果我們令 $b$ 為 $a$ 的位取反,那麽 $a\&b=0,a\oplus b=2^k-1$。所以答案就是 $2^k-1$。可以證明答案不可能超過 $2^k-1$。

復雜度 $O(\log a)$。

那麽 $a=2^k-1=(11111...)_2$ 怎麽辦呢?似乎大多數人都是暴力打出一個表然後直接調用的……

我的做法是:我們發現對於一個 $1\le b<a$,有 $a\&b=b,a\oplus b=a-b$。

那麽 $\gcd(a\&b,a\oplus b)=\gcd(b,a-b)=\gcd(a,b)$!!!

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

總復雜度 $O(q\sqrt{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\n",c-1); else{ bool flag=false; for(int i=2;i*i<=n;i++) if(n%i==0){printf("%d\n",n/i);flag=true;break;} if(!flag) printf("1\n"); } } }
View Code

CF1110C Meaningless Operations(思想題)