• 洛谷3708 koishi的数学题 (递推)


    推了一会,一开始想用“余数求和”这题的方法,复杂度有点高,除法分块跑不过1e6,但是其实这题有比较巧妙的写法。我们考虑f(n)和f(n+1)的递推关系,在不考虑取模的情况下,f(n+1)=f(n)+n+n+1这个是显然的(相当于每个数加一,再加上n+1),但是我们有恰好取模后为0的情况,我们记d(x)为一个数的约数和,那么f[i]=f[i-1]+2*i-1-d[i];即我们要减去取模后变成0的数,那么这题就等价于线性求d(n)啦,考虑到d(n)是个类似积性函数的东西,我们可以线性筛晒出来。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    const ll N=1e6+5;
    ll d[N],f[N],b[N],a[N],l,sum[N];
    int main(){
        ll n;scanf("%lld",&n);
        for(ll i=2;i<=n;i++){
            if(!b[i]) b[i]=1,a[++l]=i,sum[i]=1+i,d[i]=sum[i];
            for(ll j=1;j<=l&&a[j]*i<=n;j++){
                b[i*a[j]]=1;
                if(i%a[j]==0){
                    sum[i*a[j]]=sum[i]*a[j]+1;
                    d[i*a[j]]=d[i]/sum[i]*sum[i*a[j]];break;
                }d[i*a[j]]=d[i]*sum[a[j]];
                sum[i*a[j]]=1+a[j];
            }
        }
    //	for(ll i=1;i<=n;i++){
    //		for(ll j=1;j*j<=i;j++)
    //		if(i%j==0) d[i]+=j+i/j;
    //		ll t=sqrt(i);if(t*t==i) d[i]-=t;
    //	}
        for(ll i=1;i<=n;i++) f[i]=f[i-1]+2*i-1-d[i];
        for(ll i=1;i<=n;i++) printf("%lld ",f[i]+(n-i)*i-1);
    }
    
  • 相关阅读:
    stl
    Chopsticks Hdu1500
    Dp Hdu1421 搬寝室
    AOj448有趣的矩阵
    树状数组Hdu1541
    树状数组Hdu1166
    Floyd最小环Hdu1599
    三大主流ETL工具选型
    ETL概述
    POI操作Excel常用方法总结
  • 原文地址:https://www.cnblogs.com/BLUE-EYE/p/9574858.html
Copyright © 2020-2023  润新知