洛谷原題:https://www.luogu.org/problem/P3708
思路:
首先當然是n^2算法(30分),略過
首先對該函數進行變形(以下除法皆爲整除):
f(x)=x-(x/i)*i(1<=i<=n)
f(x)=nx-(x/i)*i(1<=i<=n)
我們考慮一下遞推,就是從f(x)推到f(x+1)
我們考慮一下x變成x+1會使得那些ii的值發生變化
顯然是當i爲x+1的約數時
這個非常顯然了,因爲x+1和x一定是互質的,所以x+1的約數肯定不是x的約數,於是當x變成x+1之後這些x+1的約數在下去整符號裏的值也會變大1
乘上後面的i顯然後面的式子就是增加了x+1的所有約數的和
所以問題就化爲了如何求一個數的約數和了
有n ln n(≈nlogn)算法
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j+=i) f[j]+=i;
這樣複雜度就等於n/1+n/2+...+n/n=n*(1+1/2+1/3+...1/n) 後面好像是調和級數,當n極大時是≈ln n (百度查的結論,不確定描述正確性,求指正)
代碼:
#include<iostream>
#include<cstdio>
#include<cstring>
#define MAXN 1000001
using namespace std;
int n;
long long sub[MAXN];
long long ans[MAXN];
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j+=i) sub[j]+=i;
}
ans[1]=1;
for(int i=2;i<=n;i++) ans[i]=ans[i-1]+sub[i];
for(int i=1;i<=n;i++)
{
printf("%lld ",(long long)n*i-ans[i]);
}
}
總結:數論好難啊!!