bzoj2190: [SDOI2008]儀仗隊(尤拉函式)

Hanks_o發表於2017-10-27

題目傳送門
基礎太弱導致我現在才去學尤拉函式。

解法:
尤拉函式就是求小於等於x且與x互質的數的個數。
先把左下角換到左上角(等效)
把1,1看做原點。
斜率相同的點中只有一個點能看到。
斜率為(x-1)/(y-1)
那麼只有互質的時候才是離原點最近的點。
所以我們就要求與每一個x-1互質個個數。
所以篩phi。然後求出ans=1~n-1的phi(尤拉函式)
然後因為尤拉函式求得是小於等於x的,所以ans就是對角線左邊的方案數。
還有對角線右邊的三角形,還有對角線上的第一個點。
所以最後答案是ans*2+1

程式碼實現:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int prime[11000],phi[41000];
int n;
void get_phi() {  //線性篩phi
    memset(phi,0,sizeof(phi));
    phi[1]=1;int len=0;
    for(int i=2;i<=n;i++) {
        if(phi[i]==0) {
            prime[++len]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=len&&i*prime[j]<=n;j++) {
            int t=i*prime[j];
            if(i%prime[j]==0) {
                phi[t]=phi[i]*prime[j];break;
            }
            phi[t]=phi[i]*(prime[j]-1);
        }
    }
}
int main() {
    scanf("%d",&n);
    get_phi();
    int ans=0;
    for(int i=1;i<n;i++)
        ans+=phi[i];
    printf("%d\n",ans*2+1);
    return 0;
}

相關文章