1. 程式人生 > >lg3708 koishi的數學題 [數學]

lg3708 koishi的數學題 [數學]

ace des 如果 fontsize line str 分享圖片 差分 net

Description

輸入一個整數n,設\(f(x)=\sum_{i=1}^n x~mod~i\),你需要輸出 $ f(1),f(2)...f(n)$

Input

一個正整數n。

Output

用空格分隔的n個整數$f(1),f(2)...f(n) $

思路

老師上課講的例題,方法真的很神奇。

觀察樣例,然後再繼續觀察。如果還是沒有發現什麽的話,就模擬打出一張表好了:(橫坐標為x, 縱坐標為y)
技術分享圖片
有沒有發現什麽神奇的地方。顯然每一橫行加起來就是答案,神奇的是在於縱行!(不要問我怎麽發現的)

每一縱行的意義即是,對於一個固定的i, x遞增時的\(x ~mod ~ i\)。可以發現它是以i個為循環的數列。

處理上面一個數列復雜度較高,但是我們可以這樣處理:發現對於一個固定的i, x遞增時的\(x-(x ~mod ~ )i\),它便是每i項增加i的一個數列。於是我們可以每i個數打一個標記,標記意為增加i。

然後我們可以發現,f(x)可以從f(x-1)推到,便是$f(x-1)+n-1-標記。(類似於前綴和+差分維護吧)

代碼

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
long long n,j,temp,ans,tag[MAXN]; //tag數組即為標記

int main(){
  scanf("%lld",&n);
  for(int i=2; i<=n; i++)
      for(int j=i; j<=n; j+=i)
          tag[j]+=i;  //處理tag數組,每i位加i
  for(int i=1; i<=n; i++)
  {
      ans+=n-tag[i]-1;
      printf("%lld ",ans); //遞推得出答案
  }
  return 0;
}

lg3708 koishi的數學題 [數學]