「NOIP2018模拟9.10」公约数 - 找规律 - gcd
公约数
Time Limits: 1000 ms
Memory Limits: 262144 KB
Detailed Limits
Input
输入共一行,一个正整数\(n\)。
Output
输出共一行,一个正整数表示答案。
Sample Input
3
Sample Output
1
Data Constraint
对于\(30\)%的数据满足\(n\leq1000\)
对于\(60\)%的数据满足\(n\leq1\times10^{5}\)
对于\(100\)%的数据满足\(n\leq1\times10^{7}\)
Hint
只有\((2,3)\)满足要求。
分析
我在打表的时候得出一个结论:满足条件的\(gcd(a,b) = a\)^\(b = a-b\) (设\(a\)为较大数)
此时\(a\)、\(b\)都是\(a-b\)也就是\(gcd(a,b)\)的倍数
我们用\(i\)枚举\(a-b\),用\(j\)枚举\(a\),此时\(j\)始终为\(i\)的倍数
这时\(a=j\),\(b=j-i\)
那么\(a\)^\(b = a-b\)就等价于\(j\)^\((j-i) = i\)
枚举即可 复杂度\(O(nlogn)\)
代码
#include<cstdio>
#include<cctype>
#define rg register
#define int long long
using namespace std;
inline int read(){
rg int f=0,x=0;
rg char ch=getchar();
while(!isdigit(ch)) f|=(ch=='-'),ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
int n,ans;
signed main() {
n=read();
for(rg int i=1;i<=n;++i)//枚举(a-b)
for(rg int j=(i<<1);j<=n;j+=i)//枚举 a
ans+=((j^(j-i))==i);
printf("%lld",ans);
return 0;
}