2020 CCPC 网络赛1002—— Graph Theory Class

刚签完到就上min_25筛233
好!很有精神!

思路:构造
每个点若要加入原有图,那么所需的代价最低是它本身,最多与2相连,也就是这个数的两倍。显然,最终的答案是10^10以内的质数和*2+合数和。
也就是10^10以内的所有数之和+质数和
我们考虑用min_25筛解决
我们设F(i) = i(当i为质数的时候)
显然质数之和为
在这里插入图片描述
我们设函数g(n,j)为求出1到n中,i为质数或i的最小质因子大于当前第j个质数的f ( i )。其中 p j p_j pj表示第j个质数
在这里插入图片描述
显然我们要求的就是g(n,0)
对于这个式子,我们可用递归的方式解决
在这里插入图片描述
好吧,相信到这里,会的还是会,不会的还是不会(bushi)
最后,上代码

#include<bits/stdc++.h>
#define N 200010
#define ll long long
#define int long long
using namespace std;
ll mod = 0;
bool Prime[N];
int tot;
ll p[N];
ll n, sq, w[N], m, sum1[N], g1[N], id1[N], id2[N];
void xxs() { // 线性筛模板 
    for(int i = 2; i <= sq; i++) {
        if(!Prime[i]) ++tot, p[tot] = i;
        for(int j = 1; p[j] * i <= sq && j <= tot; j++) {
            Prime[p[j] * i] = 1;
            if(i % p[j] == 0) break;
        }
    }
    for(int i = 1; i <= tot; i++) {
    //注意这里的+p[i],实际上是相当于+x,如果求质数个数,那就是+1,如果是质数个数的平方和,那就是p[i]*p[i]
        sum1[i] = (sum1[i - 1] + p[i]) % mod;
    }
}
ll getid(ll x) { 
    if(x <= sq) return id1[x];
    else return id2[n / x];
}
ll f1(ll x) { // 1~x 实际上是f(i) 的前缀和
    x %= mod;
    return x * (x + 1) / 2 % mod;
}
void min_25_dp()//求g(i,0),递推做 
{
    for(int i = 1; i <= tot; i++) {
        for(int j = 1; j <= m && p[i] * p[i] <= w[j]; j++) {
            g1[j] = (g1[j] - p[i] * (g1[getid(w[j] / p[i])] - sum1[i - 1]) % mod + mod) % mod;
        }
    }	
}
signed main() {
	
    scanf("%lld", &n),n++; 
    scanf("%lld",&mod);
	sq = sqrt(n), xxs();
    
    for(ll l = 1, r; l <= n; l = r + 1) {
        r = (n / (n / l)), w[++m] = (n / l);
        g1[m] = f1(w[m]) - 1;
        if(w[m] <= sq) id1[w[m]] = m;
        else id2[n / w[m]] = m;
    }
	min_25_dp();
    printf("%lld\n", (g1[getid(n)]%mod+(n)*(n+1)/2%mod-5) % mod);//	所有数之和+质数和,减5是因为从2开始,并且2不算
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值