1. 程式人生 > 實用技巧 >【POJ2478】Farey Sequence

【POJ2478】Farey Sequence

題目連結

Farey Sequence

題目描述

The Farey Sequence Fn for any integer \(n\) with \(n \ge 2\) is the set of irreducible rational numbers \(a/b\) with \(0 < a < b \le n\)and \(gcd\)(\(a,b\))$ = 1$ arranged in increasing order. The first few are
\(F_2 = {1/2}\)
\(F_3 = {1/3, 1/2, 2/3}\)
\(F_4 = {1/4, 1/3, 1/2, 2/3, 3/4}\)


\(F_5 = {1/5, 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5}\)

You task is to calculate the number of terms in the Farey sequence Fn.

輸入格式

There are several test cases. Each test case has only one line, which contains a positive integer \(n\) (\(2 \ge n \ge 10^6\)). There are no blank lines between cases. A line with a single \(0\)

terminates the input.

輸出格式

For each test case, you should output one line, which contains \(N\)(\(n\)) ---- the number of terms in the Farey sequence \(F_n\).

樣例輸入

2
3
4
5
0

樣例輸出

1
3
5
9

題解

\(F_n=\sum_{i=1}^n\sum_{j=i+1}^n[gcd(i,j)==1]\)
我們假設\(f_n\)\(n\)以內\(gcd\)\(1\)的對數,視(\(i,j\))和(\(j,i\))相同,包括(\(1,1\)

)。
那麼\(n\)以內\(gcd\)\(2\)的對數為\(f_{n/2}\)
以此類推,\(n\)以內\(gcd\)\(i\)的對數為\(f_{n/i}\)
那麼我們可以得到如下等式:
\(\sum_{i=1}^nf_{n/i}=\sum_{i=1}^ni=n*(n+1)/2\)
因為\(f_n\)中(\(i,j\))和(\(j,i\))不重複計算,所以上述等式成立。
我們再把等式左邊的\(f_n\)提出來,
\(f_n=n*(n+1)/2-\sum_{i=2}^nf_{n/i}\)
那麼我們就得到了\(f_n\)的遞推式,我們考慮到\(f_n=F_n+1\),因為題目中要求不包含(\(1,1\))
所以我們可以用遞推式求\(f_n\),因為\(n \le 10^6\),所以我們記憶化一下就可以過了。
ps:據說也可以用尤拉函式字首和做,這裡就不多講了QWQ。

#include<cstdio>
using namespace std;
int n;
long long f[1000009];
long long fd(long long x){
    if(f[x]!=0) return f[x];
    f[x]=x*(x+1)/2;
    for(long long i=2;i<=x;i++){
        f[x]-=((x/(x/i))-i+1)*fd(x/i);//因為一段區域內x/i相等,fd(x/i)相等,所以可以優化一下
        i=x/(x/i);
    }
    return f[x];
}
int main(){
    f[1]=1;
    while(1){
        scanf("%d",&n);
        if(n==0) break;
        printf("%lld\n",fd(n)-1);
    }
    return 0;
}