2020 ICPC 瀋陽站 I - Rise of Shadows 題解
題面看這裡
題目大意
給你一個一天有 \(H\) 小時、一小時有 \(M\) 分鐘的表和一個正整數 \(A\),問一天內有多少個整數時刻,使得分針與時針的夾角小於等於 \(\displaystyle\frac{2\pi A}{HM}\)。
題目分析
分針轉速 \(w_1=\displaystyle \frac{2\pi}{M}\),時針轉速 \(w_2=\displaystyle\frac{2\pi}{HM}\),當前時刻為 \(T\);
一天有 \(HM\) 個整數時刻,即 \(T\in[0,HM)\);
於是對於每一個時刻,我們判斷一下兩個指標的夾角 \(\theta\)
方法一:數論
顯然有:
\[\theta=(w_1-w_2)T=\displaystyle\frac{2\pi(H-1)T}{HM} \]注意到 \(\theta\in[0,2\pi]\),所以還要對 \(2\pi\) 取個模(分針轉一圈又轉回來了),即:
\[\theta=\displaystyle\frac{2\pi(H-1)T}{HM}\mod{2\pi} \]同時因為兩個指標之間的夾角可以選到兩個數值,逆時針轉有一個夾角,順時針轉有一個夾角,這裡我們肯定是選更小的角來判斷是否滿足條件,即最終我們要求的是:
可以轉化為:
\[\sum_{T=0}^{HM}[\ \theta\leq\frac{2\pi A}{HM}\or\theta\ge2\pi-\frac{2\pi A}{HM}\ ] \]把 \(\theta=\displaystyle\frac{2\pi(H-1)T}{HM}\mod{2\pi}\) 代入並化簡得:
\[\sum_{T=0}^{HM}[\ T(H-1)\mod{HM}\leq A\or T(H-1)\mod{HM}\geq HM-A\ ] \]此時我們其實就可以把 \(HM\)
當 \(A=HM/2\) 時,問題等價於”一天內有多少個整數時刻,使得分針與時針的夾角小於等於 \(\pi\)“,顯然每個時刻都滿足(如果順時針看夾角大於 \(\pi\),那逆時針看一定小於,反之亦然),此時答案為 \(HM\);
當\(A\neq HM/2\) 時,若有 \(T(H-1)\mod{HM}\leq A\),則一定不會有 \(T(H-1)\mod{HM}\geq HM-A\),所以答案就是這兩部分的貢獻相加。
我們令 \(G=\gcd(H-1,HM)\)。
先計算式子的左邊:
\[\sum_{T=0}^{HM}[\ T(H-1)\mod{HM}\leq A\ ] \]當 \(G=1\) 時 ,因為 \(T\in[0,HM)\),由同餘的性質可得 \(T(H-1)\mod{HM}\) 一定取遍了 \(0\sim HM\) 的每個數,即構成一個模 \(HM\) 的完全剩餘系,此時這部分的貢獻就是 \(A+1\)。
當 \(G\neq1\) 時,我們利用同餘的另一個性質: \(\displaystyle ac\equiv bc\pmod d\iff a\equiv b\pmod{\frac{d}{(c,d)}}\),把式子轉化為:
\[\sum_{T=0}^{HM}[\ \frac{T(H-1)}{G}\mod{\frac{HM}{G}}<=\lfloor\frac AG\rfloor\ ] \]相當於我們把 \(T\in[0,HM)\) 平均分成了 \(G\) 段,且每段的 \(T\mod\displaystyle\frac{HM}G\) 都取到了 \(0\sim \displaystyle\frac{HM}G\) 的每個數,同時有 \(\gcd(\displaystyle\frac{H-1}G,\displaystyle\frac{HM}G)=1\),因此這裡的每一小段,其實就等價於上面 \(G=1\) 的情況,只是 \(T\) 的範圍和模數變了下而已,此時每一小段都造成了 \(\displaystyle \lfloor\frac AG\rfloor+1\) 的貢獻,總貢獻就是 \(G*(\displaystyle \lfloor\frac AG\rfloor+1)\)。
再看式子右邊:
\[\sum_{T=0}^{HM}[\ T(H-1)\mod{HM}\geq HM-A\ ] \]同樣地,當 \(G=1\) 時,跟上面一樣分析一波,發現其實是等價的(這裡顯然具有對稱性),只不過因為 \(T\) 不能取到 \(HM\),所以貢獻只有 \(A\)(\([HM-A,HM-1]\) 共有 \(A\) 個數)。
當 \(G\neq1\) 時,也同上,把 \(T\) 分成 \(G\) 段,總貢獻是 \(G*\displaystyle \lfloor\frac AG\rfloor\)。
因此答案就是:\(G*(\displaystyle 2\lfloor\frac AG\rfloor+1)\)
#include<bits/stdc++.h>
using namespace std;
int main(){
long long H,M,A;
cin >> H >> M >> A;
if(H*M==A*2){
cout << H*M;
}
else {
long long G=__gcd(H-1,H*M);
cout << G*(2*(A/G)+1);
}
}
方法二:類歐幾里得
待填坑~~