Codeforces 1110C (思維+數論)
阿新 • • 發佈:2019-02-08
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 (思維+數論)