「NOIP2018模拟9.10」公约数 - 找规律 - gcd

无原题地址

公约数


Time Limits: 1000 ms
Memory Limits: 262144 KB
Detailed Limits


Description

给定一个正整数\(n\),在\([1,n]\)的范围内,求出有多少个无序数对\((a,b)\)满足\(gcd(a,b) = a\) \(xor\) \(b\)

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;
}

转载于:https://www.cnblogs.com/horrigue/p/9622019.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值