标签:
Description
Input
Output
Sample Input
Sample Output
由题意,如果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; }
标签:
原文地址:http://www.cnblogs.com/andyqsmart/p/4526555.html