洛谷 P2158 [SDOI2008]儀仗隊 解題報告
P2158 [SDOI2008]儀仗隊
題目描述
作為體育委員,C君負責這次運動會儀仗隊的訓練。儀仗隊是由學生組成的N * N的方陣,為了保證隊伍在行進中整齊劃一,C君會跟在儀仗隊的左後方,根據其視線所及的學生人數來判斷隊伍是否整齊(如下圖)。 現在,C君希望你告訴他隊伍整齊時能看到的學生人數。
輸入輸出格式
輸入格式:
共一個數N
輸出格式:
共一個數,即C君應看到的學生人數。
說明
對於 100% 的數據,1 ≤ N ≤ 40000
今天看了一天的歐拉函數,明天月考放飛自我了...
對於歐拉函數
將正整數\(N\)用算術基本定理進行分解\(N=\prod_{i=1}^k{c_i}^{m_i}\),\(k\)
則\(φ(N)=N* \prod_{i=1}^{k} (1-\frac{1}{c_i})\)
證明方法需要用到容斥原理。
幾個性質:
若\(gcd(a,b)=1\),則\(φ(ab)=φ(a)*φ(b)\)
積性函數定義啊。若質數\(q\)滿足\(q|n\)且\(q^2|n\),則\(φ(q)=φ(n/q)*q\)
代入定義式可以得到若質數\(q\)滿足\(q|n\)且\(q^2 \nmid n\),則\(φ(q)=φ(n/q)*(q-1)\)
由積性函數性質得到\(\sum_{d|n}φ(d)=n\)
先證明是積性函數,再討論單因子即可\(φ(n)*n/2=\sum_{d},gcd(d,n)=1\)
成對存在
在看看這題。
我們以左下角為原點,第一行為\(x\)軸,第一列為\(y\)軸。
則若點\((x,y)\)能被看見,則\((dx,dy)\),\(d \in N^*\)會被遮擋
則點\((x,y)\)能被看見的條件為\(gcd(x,y)=1\),即它們互質。
那麽對此,我們可以將我們要求的轉換為\(\sum_{i=2}^n φ(i)\)
當然這只是右下角的一部分。
加上(0,1),(1,1),(1,0)三個點,最終答案為\(3+2*(\sum_{i=2}^n φ(i))\)
對於歐拉函數的求和,我們可以借助線性篩的思想做到線性的復雜度
可以參考代碼。
code:
#include <cstdio> const int N=40010; int v[N],prime[N],eu[N],cnt=0,ans=0,n; void eular() { for(int i=2;i<=n;i++) { if(!v[i]) { v[i]=i; prime[++cnt]=i; eu[i]=i-1; ans+=eu[i]; } for(int j=1;j<=cnt;j++) { int tmp=i*prime[j]; if(v[i]<prime[j]||tmp>n) break; v[tmp]=prime[j]; eu[tmp]=eu[i]*(i%prime[j]?prime[j]-1:prime[j]); ans+=eu[tmp]; } } } int main() { scanf("%d",&n); n--; if(!n) {printf("0\n");return 0;} eular(); printf("%d\n",(ans<<1)+3); return 0; }
2018.5.28
洛谷 P2158 [SDOI2008]儀仗隊 解題報告