【onecode】OCWA提高模擬賽十一 簡單數學題

洛谷原題: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]);
	}
}

總結:數論好難啊!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章