码迷,mamicode.com
首页 > 其他好文 > 详细

ACM学习历程—HDU1719 Friend(数论)

时间:2015-05-24 23:11:08      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:

Description

Friend number are defined recursively as follows.
(1) numbers 1 and 2 are friend number;
(2) if a and b are friend numbers, so is ab+a+b;
(3) only the numbers defined in (1) and (2) are friend number.
Now your task is to judge whether an integer is a friend number.
 

Input

There are several lines in input, each line has a nunnegative integer a, 0<=a<=2^30.
 

Output

For the number a on each line of the input, if a is a friend number, output “YES!”, otherwise output “NO!”.
 

Sample Input

3
13121
12131
 

Sample Output

YES!
YES!
NO!

 

由题意,如果n = a+b+ab,a和b都是friend number

那么(n+1) = (a+1) * (b+1),

然后我记friend number叫做好数。

那么2和3是好数。

然后两个好数相乘也是好数。

由于其他数首先都是由2和3生出的,所以好数必然是2^k * 3^p。

接下来证明所有2^k * 3^p都是好数。

反证:

若2^k * 3^p不是好数,那么2^(k-1) * 3^p必然也不是好数,否则2^(k-1) * 3^p和2相乘会导致2^k * 3^p也是好数。

然后递降下来说明了3^p也不是好数。

同理说明了3不是好数。

矛盾!

所以所有2^k * 3^p都是好数。

于是判断好数只需要先把二因子除去,这里采用位运算优化。

然后除去3因子,判断最后结果是不是1。这里打表保存了3的所有指数密进行判断。

能判断好数了,自然能判断friend number了。不过需要对0进行特判。

 

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#define LL long long

using namespace std;

const int maxn = 1<<30;

set <LL> s;

void Init()
{
    int now = 2;
    s.insert(1);
    for (;;)
    {
        if (now > maxn)
            break;
        s.insert(now);
        now = 2*now + 1;
    }
    now = 5;
    for (;;)
    {
        if (now > maxn)
            break;
        s.insert(now);
        now = 3*now + 2;
    }

    now = 11;
    for (;;)
    {
        if (now > maxn)
            break;
        s.insert(now);
        now = 6*now + 5;
    }
}

bool judge(LL n)
{
    if (no.find(n) != no.end())
        return false;
    if (s.find(n) != s.end())
        return true;
    n++;
    int len = sqrt(n);
    for (int i = 2; i <= len; ++i)
    {
        if (n % i)
            continue;
        if (judge(i-1)&&judge(n/i-1))
        {
            s.insert(n);
            return true;
        }
    }
    no.insert(n);
    return false;
}

int main()
{
    //freopen("test.in", "r", stdin);
    LL n;
    Init();
    while (scanf("%I64d", &n) != EOF)
    {
        if (judge(n))
            printf("YES!\n");
        else
            printf("NO!\n");
    }
    return 0;
}

 

ACM学习历程—HDU1719 Friend(数论)

标签:

原文地址:http://www.cnblogs.com/andyqsmart/p/4526555.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!