hdu5514
hdu5514
題意
\(m\) 個石子繞成一圈,編號\([0, m - 1]\)。有 \(n\) 個青蛙從 \(0\) 號石子出發,給出每個青蛙的步長,青蛙無限跑圈。問哪些石子至少被一個青蛙經過,求這些石子的編號之和。
分析
假設某個青蛙的步長 \(x\),則一共會經過 $ \frac{m - 1}{x} + 1$ 個石子(包括 \(0\) )。可以用等差數列求和公式計算貢獻。
然后找出 \(m\) 的所有因子并考慮哪些因子可能要計算貢獻。
例如步長為 \(2\) 和 \(3\) 的計算后,步長為 \(6\) 的情況被計算了兩次(或者說 \(6\) 的倍數的編號被計算了兩次),應該減去一次,用一個數組記錄某個步長被計算了幾次貢獻,在統計答案的時候減去即可。
code
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN = 1e4 + 10; int a[MAXN]; int fac[MAXN]; int vis[MAXN]; // vis[i]表示fac[i]是否可能要計算貢獻,如果為 0 一定不計算貢獻 int num[MAXN]; // num[i]表示fac[i]被計算了幾次貢獻 int main() {int T, kase = 1;scanf("%d", &T);while(T--) {memset(vis, 0, sizeof vis);memset(num, 0, sizeof num);int n, m;scanf("%d%d", &n, &m);int fc = 0;for(int i = 1; i * i <= m; i++) {if(m % i == 0) {fac[fc++] = i;if(i * i != m) fac[fc++] = m / i;}}sort(fac, fac + fc);for(int i = 0; i < n; i++) {scanf("%d", &a[i]);a[i] = __gcd(a[i], m);for(int j = 0; j < fc; j++) {if(fac[j] % a[i] == 0) {vis[j] = 1;}}}ll ans = 0;for(int i = 0; i < fc - 1; i++) {ll k = (m - 1) / fac[i];ans += (k + 1) * k * fac[i] / 2 * (vis[i] - num[i]);for(int j = i + 1; j < fc - 1; j++) {if(fac[j] % fac[i] == 0) {num[j] += vis[i] - num[i];}}}printf("Case #%d: %lld\n", kase++, ans);}return 0; }轉載于:https://www.cnblogs.com/ftae/p/7618031.html
總結
- 上一篇: Unskilled in English
- 下一篇: java和ccnp哪个难_新版思科网络工