2015-2016 ACM ICPC Baltic Selection Contest K. Profact


题目描述:

http://codeforces.com/gym/100796/problem/K

题解:

水题,但是还是傻了一会.
最开始一定会想,从大的可以整除的阶层往下除.但这是不对的. 比如fac[17]和fac[18], 不知道要不要除18,但是推一下就能发现,只有17 18 和 13 14 15 需要特殊考虑,其他的都是只除到那个质数就行了. 注意,一定是质数,不能多除

重点:

1.发现不定情况很少
2.其他情况只除到质数,而不是随便除

代码:
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

typedef long long ll;

const int maxn  = 30 + 10;
const ll M = 1e18 + 100;
ll fac[maxn];
ll a, k;
int n;

int dfs(ll x) {
    if(x == 1 || x == 2)
        return 1;
    int ans = 0;
    if(x % 19 == 0) {
        if(x % fac[19] == 0) {
            return dfs(x / fac[19]);
        }
        return 0;
    }
     if(x % 17 == 0) {
         if(x % fac[18] == 0)
             ans += dfs(x / fac[18]);
         if(x % fac[17] == 0)
             ans += dfs(x / fac[17]);
        if(ans > 0)
            return 1;
        return 0;
    }
    if(x % 13 == 0) {
        if(x % fac[15] == 0)
            ans += dfs(x / fac[15]);
        if(x % fac[14] == 0)
            ans += dfs(x / fac[14]);
        if(x % fac[13] == 0)
            ans += dfs(x / fac[13]);
        if(ans > 0)
            return 1;
        return 0;
    }
    if(x % 11 == 0) {
        if(x % fac[11] == 0) {
            return dfs(x / fac[11]);
        }
        return 0;
    }
     if(x % 7 == 0) {
        if(x % fac[7] == 0) {
            return dfs(x / fac[7]);
        }
        return 0;
    }
      if(x % 5 == 0) {
        if(x % fac[5] == 0) {
            return dfs(x / fac[5]);
        }
        return 0;
    }
       if(x % 3 == 0) {
        if(x % fac[3] == 0) {
            return dfs(x / fac[3]);
        }
        return 0;
    }
        if(x % 2 == 0) {
        if(x % fac[2] == 0) {
            return dfs(x / fac[2]);
        }
        return 0;
    }
    return 0;
}

void solve() {
    if(dfs(a) == 1)
        printf("YES\n");
    else
        printf("NO\n");
}

int main() {
    //freopen("k.txt", "r", stdin);
    fac[1] = 1;
    for(int i = 2; i <= 30; i++) {
        // printf("111 %d\n", i);
        if(fac[i - 1] >= M) {
            //printf("%I64d  %I64d **\n", fac[i - 1], M);
            k = i - 1;
            break;
        }
        fac[i] = fac[i - 1] * i;
    }
    //printf("%I64d  %I64d   %I64d\n", k, fac[k], fac[13]);
    while(scanf("%d", &n) != EOF) {
        for(int i = 0; i < n; i++) {
            scanf("%I64d", &a);
            solve();
        }
    }
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值