狄利克雷卷积、杜教筛学习

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_25576697/article/details/82228190

今天才知道有杜教筛这个逆天的东西,实在惭愧,学习了,先放上链接,后面再补题。

https://blog.csdn.net/hzj1054689699/article/details/75091655

这个也写得很好:https://blog.csdn.net/u011495472/article/details/50460409

hdu5608

function

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 958    Accepted Submission(s): 369

Problem Description

There is a function f(x),which is defined on the natural numbers set N,satisfies the following eqaution

N2−3N+2=∑d|Nf(d)

calulate ∑Ni=1f(i)  mod 109+7.

Input

the first line contains a positive integer T,means the number of the test cases.

next T lines there is a number N
T≤500,N≤109

only 5 test cases has N>106.

Output

Tlines,each line contains a number,means the answer to the i-th test case.

Sample Input

1

3

Sample Output

2

题意:如题

思路:

这里写图片描述

对于前面数量级小的部分可以先预处理计算出来,后面部分通过杜教筛筛出来。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<map>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn = 1e6+10;
ll ans[maxn];
ll inv;
map<int,ll>mp;
map<int,ll>::iterator it;
ll quick_mod(ll a,ll b)
{
    ll ans = 1;
    while(b)
    {
        if(b&1)ans = (ans * a)%mod;
        b>>=1;
        a = (a * a)%mod;
    }
    return ans;
}
void init()
{
    for(int i =0;i<maxn;i++)
    {
        ans[i] = (ll)(i-1)*(i-2)%mod;
    }
    for(int i = 1;i<maxn;i++)
    {
        for(int j = (i<<1);j<maxn;j+=i)
        {
            ans[j]-=ans[i];
            if(ans[j]<0)ans[j]+=mod;
        }
    }
    for(int i = 2;i<maxn;i++)
    {
        ans[i] += ans[i-1];
        if(ans[i]>mod)ans[i]-=mod;
    }
    inv = quick_mod(3ll,mod-2);
}
ll getans(int x)
{
    if(x<maxn)return ans[x];
    it = mp.find(x);
    if(it!=mp.end())return it->second;
    ll res = ((((ll)x*(x-1))%mod*(x-2)%mod)*inv)%mod;
    int j;
    for(int i = 2;i<=x;i = j+1)
    {
        j = x/(x/i);
        res  = (res - (getans(x/i)*(j-i+1)%mod)%mod+mod)%mod;
    }
    return mp[x] = res;
}
int main()
{
    init();
    mp.clear();
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        printf("%lld\n",getans(n));
    }
}

猜你喜欢

转载自blog.csdn.net/qq_25576697/article/details/82228190