[Codeforces546D]Soldier and Number Game[dp][实现][素数筛][分解整数][数学]

41 篇文章 0 订阅
17 篇文章 0 订阅

原题链接:[Codeforces546D]Soldier and Number Game[dp][实现][素数筛][分解整数][数学]

题意分析:本题从实质上来说,就是给你两个整数a, b。求出a, a - 1, a - 2........b + 1这些整数能被拆分成多少个素数相乘,把每个的拆分结果相加起来。

例如 a = 10, b = 2. 那么ans = 1(3) + 2(4) + 1(5) + 2(6) + 1(7) + 3(8) + 2(9) + 2(10) = 14

解题思路:由于题目给的测试点t范围很大,这样就要把每个整数能拆分的个数预先处理。我个人采用动归的思想,dp[i]代表i能被拆分成的最大素数个数。所以有:如果这个数是素数,则有dp[i] = 1.否则dp[i] = dp[i / j] + 1;(i % j == 0 && j为素数)因为实质上,dp[i]和dp[i / j] 就是多了个素数j。筛选素数的时候要使用素数筛法,否则超时。另外,dp[i]最终还要处理为前i个dp[i]的和,这样给出的答案的时间复杂度就是O(1)了。

个人感受:昨晚比赛的时候思路都是有的。就是筛选素数的时候用了暴力筛选,最后dp也没有优化成和,果断被hack了TAT怪我太蠢。不过想到用dp我也是好开桑的说,和学长的代码比了下,我这个预处理CPU占用率几乎为0~~~另外,早上交的时候是用cin输入,还是没有吃够『大数据就要用scanf』的亏啊。。。。

具体代码如下:

#include <iostream>  
#include <cstdio>  
#include <algorithm>  
#include <cstring>  
using namespace std;  
const int MAXN = 5000005;  
typedef long long ll;  
ll dp[MAXN];  
bool is[MAXN]; //第i个数是否为素数  
int prime[MAXN], p;  
  
void seive() { //素数筛法  
    memset(is, true, sizeof is);  
    for(ll i = 2; i <= MAXN; ++i) {  
        if(is[i]) {  
            prime[p++] = i; //把素数存下来  
            for(ll j = i * i; j <= MAXN; j += i) is[j] = false;  
        }  
    }  
}  
  
int main() {  
    seive();  
    for (int i = 2; i < MAXN; ++i)  
    {  
        if (is[i]) //如果第i个是素数  
        {  
            dp[i] = 1;  
            continue;  
        }  
        for (int j = 0; j < p; ++j) //找到第一个是它整除的数  
        {  
            if (i % prime[j] == 0)  
            {  
                dp[i] = dp[i / prime[j]] + 1;  
                break;  
            }  
        }  
    }  
    for (int i = 3; i < MAXN; ++i) //处理为前i个和  
        dp[i] += dp[i - 1];  
    int t;  
    scanf("%d",&t);  
    while (t --)  
    {  
        int a, b;  
        scanf("%d %d", &a, &b);  
        printf("%I64d\n", dp[a] - dp[b]);  
    }  
    return 0;  
}  



评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值