1. 程式人生 > >Codeforces 1110C (思維+數論)

Codeforces 1110C (思維+數論)

divide code lin lse contest 分析 i++ 我們 str

題面

傳送門

分析

這種數據範圍比較大的題最好的方法是先暴力打表找規律

通過打表,可以發現規律如下:

定義\(x=2^{log_2a+1}\) (註意,cf官方題解這裏寫錯了,官方題解中定義\(x=2^{log_2a}\)是有問題的

(1) 若\(a \neq 2^x-1\)

? 則當\(b=(2^x-1)\) xor a時a xor b=b=\(2^x-1\) ,a and b=0

? gcd(a xor b,a and b)=\(2^x-1\)有最大值

? (異或的性質,若a xor c =b ,則a xor b=c)

? 舉個例就很顯然了:(註意,例子中數均用二進制表示)

a=101,2^x-1=111
b=101 xor 111 =010
a xor b =111
a and b =000
gcd(111,000)=111

(2) 若\(a=2^x-1\)

? gcd(a xor b ,a and b)=\(gcd(2^x-1-b,b)\)

? 由於\(gcd(x,y)=gcd(x-y,y)\)

? \(gcd(2^x-1-b,b)=gcd(2^x-1,b)\)

? 所以我們只要找出\(2^x-1\)的最大且不為\(2^x-1\)的因數即可,可以直接試除法

?

代碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
inline int gcd(int a,int b){
    return b==0?a:gcd(b,a%b); 
}
int divide(int x){
    int sq=sqrt(x);
    int ans=1;
    for(int i=2;i<=sq;i++){
        if(x%i==0){
            ans=max(ans,i);
            ans=max(ans,x/i);
        }
    }
    return ans;
} 

int count(int x){
    int ans=0;
    while(x>0){
        x>>=1;
        ans++;
    }
    return ans;
} 

int solve(int x){
    int l=count(x);
    if((1<<l)-1==x) return divide(x);
    else return (1<<l)-1; 
}

int main(){
    int q,x;
    scanf("%d",&q);
    while(q--){
        scanf("%d",&x);
        printf("%d\n",solve(x));
    }
}

Codeforces 1110C (思維+數論)