HDU 5514 Frogs
生活随笔
收集整理的這篇文章主要介紹了
HDU 5514 Frogs
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意
有一群青蛙,一開始都在0點,有一堆圈石子,編號從0~m-1的。
青蛙只能順時針跳,每個青蛙可以一次跳a[i]格,然后所有青蛙都這樣一直跳下去,這些青蛙踩過的石子的編號和是多少?
思考
讀了題,以為是暴力set過的,想到了之前set判重,Floyd判圈等等,結果遇到了MLE(第一次遇到),嚇得我懷疑了set。
// MLE 2016-10-23#include<cstdio> #include<cstring> #include<set> using namespace std;long long step[10010];int main() {int kas, cnt = 1;scanf("%d",&kas);while(kas--){ set<long long> id;long long n, m;memset(step, 0, sizeof(step));scanf("%ld%ld",&n, &m);for(int i = 0; i<n; i++)scanf("%ld",&step[i]);for(int i = 0; i<n; i++){ long long ini = step[i]%m;set<long long> temp;while(!temp.count(ini)){ temp.insert(ini);// printf(" %ld marked\n",ini);ini = (ini+step[i])%m;}set<long long>::iterator temp_it;for(temp_it = temp.begin(); temp_it!=temp.end(); temp_it++)id.insert(*temp_it);}//cal sum of step[];set<long long>::iterator it;long long sum = 0;for(it = id.begin(); it!=id.end(); it++)sum+=*it;printf("Case#%d: %ld\n",cnt++, sum);}return 0; }然后果斷搜索題解,看到了容斥定理,才了解這道題的類型,然后找到優化方法:
對于第i只青蛙,他跳過的格子,一定是k*gcd(a[i],m)這種的
如果m小一點,我們就可以直接暴力了
當時m太大了,我們就分解m的因數之后,對于每個因數做暴力就好了
每個因數T的貢獻是 for(int i=1;i<=M/T;i++)ans += M*i;
第i只青蛙只能走到gcd(ai, m)的位置,我們就可以把m的因子提取出來,然后對青蛙能走到的因子位置打標記。(優化的關鍵) 青蛙能走到vis[i]因子位置就把vis[i]標記為1,然后num[i]表示m的第i個因子淚加的次數。如果vis[i]!=num[i]的話,就更新num。因子的個數大概是log2(m),所以時間復雜度大概為O(log2(m)2)。
當然也可以用set,但直接set不行。
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef __int64 LL; const int maxn = 100010;int p[maxn], vis[maxn], num[maxn]; int gcd (int a, int b) {return b==0 ? a : gcd(b, a%b); }int main () {int T;scanf ("%d", &T);for (int t=1; t<=T; t++){int n, m, cnt = 0;scanf ("%d %d", &n, &m);for (int i=1; i<=sqrt(m); i++){if (m % i == 0){p[cnt ++] = i;if (i * i != m)p[cnt ++] = m / i;}}sort (p, p+cnt);int u;memset (vis, 0, sizeof(vis));memset (num, 0, sizeof(num));for (int i=0; i<n; i++){scanf ("%d", &u);int temp = gcd (u, m);for (int j=0; j<cnt; j++){if (p[j] % temp == 0)vis[j] = 1;}}vis[cnt-1] = 0;LL ans = 0;for (int i=0; i<cnt; i++){if (vis[i] != num[i]){LL temp = m / p[i];ans += temp * (temp - 1) / 2 * p[i] * (vis[i] - num[i]);temp = vis[i] - num[i];for (int j=i; j<cnt; j++)if (p[j] % p[i] == 0)num[j] += temp;}}printf ("Case #%d: %I64d\n", t, ans);}return 0; }總結
以上是生活随笔為你收集整理的HDU 5514 Frogs的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不联网的计算机需要杀毒吗,杀毒软件不联网
- 下一篇: 测试用例-----听歌项目