今天才知道有杜教筛这个逆天的东西,实在惭愧,学习了,先放上链接,后面再补题。
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));
}
}