hdu 5175 Misaki's Kiss again

Misaki's Kiss again

 
 Accepts: 75
 
 Submissions: 593
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
摩天轮后,一些朋友希望再次得到Misaki的吻,所以Misaki把他们分别编号从1到N,如果他们中有人的编号是M,而且
    
    
     
     gcd(N,M)=N
    
     xor M,那么他以可以得到一个吻。
请帮助Misaki找到所有的M..
Note that:

    
    
     
     GCD(a,b)
    
     表示ab的最大公约数.

    
    
     
     AXORB
    
     表示A异或B.
输入描述
多组测试数据,
对于每组测试数据只有一个数
    
    
     
     N(0<N<=1010)
    
    
输出描述
第一行Case #x:
第二行一个数count表示有多少个M
第三行有count个数,按升序输出,中间一个空格,表示具体的M..
输入样例
3
5
15
输出样例
Case #1:
1
2
Case #2:
1
4
Case #3:
3
10 12 14
Hint
第三个样例:gcd(15,10)=5且(15 xor 10)=5, gcd(15,12)=3且(15 xor 12)=3,gcd(15,14)=1且(15 xor 14)=1
题解:1.也是看了官方题解才懂的题目。。需要对原式进行变换
  2.将gcd(n,m) = n ^ m(n > m) 变换为 gcd(n,n ^ k) = n ^ k ^ n = k(k是m的约数,n ^ k < m)
  3.可以用sqrt(n)的时间枚举所有的k,来反求m
  4.很明显,如果右面的式子成立,那么必然存在对应的m = n ^ k,也就是说,如果存在gcd(n,n ^ k) = n ^ k
 ^ n = k(k是m的约数,n ^ k < m),那么一定存在这样的m = n ^ k;
  5.反过来,是否对于每一个gcd(n,m) = n ^ m(n > m),m一定对应于一个n ^ k呢??gcd(n,m) = p =
 n ^ m ==> p ^ n = m ^ n ^ n = m ==> gcd(n,p ^ n) = p, p依旧是n的一个约数,所以枚举所有的n的约数,
就可以找到所有符合条件的m
总结:1.这个题目打表打了很长时间都没有找到规律,感觉以后再做题的时候不能一条路走到黑
  2.对于数学公式,可以尝试根据公式的概念或者定义进行变换,枚举所有表示这个公式的方法;

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
vector<LL>vec;
LL n;
LL gcd(LL a,LL b)
{
    if(b)return gcd(b,a % b);
    return a;
}
int main()
{
    int _ = 0;
    while(scanf("%I64d",&n) != EOF)
    {
        vec.clear();
        LL cnt = sqrt(n + 1) + 1;
        for(LL i = 1;i <= cnt;i++)
            if((n % i) == 0)
            {
                if((n ^ i) < n && gcd(n,n ^ i) == i)
                    vec.push_back(i ^ n);
                LL cur = n / i;
                if(cur != i && (n ^ cur) < n && gcd(n,n ^ cur) == cur)
                    vec.push_back(n ^ cur);
            }
        sort(vec.begin(),vec.end());
        cnt = unique(vec.begin(),vec.end()) - vec.begin();
        printf("Case #%d:\n%I64d\n",++_,cnt - 1);
        if(1 >= cnt)puts("");
        for(LL i = 1;i < cnt;i++)
        {
            if(i != cnt - 1)printf("%I64d ",vec[i]);
            else printf("%I64d\n",vec[i]);
        }
    }
    return 0;
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值