Frogs
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 802 Accepted Submission(s): 242
Problem Description
There are
m
stones lying on a circle, and
n
frogs are jumping over them.
The stones are numbered from 0 to m−1 and the frogs are numbered from 1 to n . The i -th frog can jump over exactly ai stones in a single step, which means from stone j mod m to stone (j+ai) mod m (since all stones lie on a circle).
All frogs start their jump at stone 0 , then each of them can jump as many steps as he wants. A frog will occupy a stone when he reach it, and he will keep jumping to occupy as much stones as possible. A stone is still considered ``occupied" after a frog jumped away.
They would like to know which stones can be occupied by at least one of them. Since there may be too many stones, the frogs only want to know the sum of those stones' identifiers.
The stones are numbered from 0 to m−1 and the frogs are numbered from 1 to n . The i -th frog can jump over exactly ai stones in a single step, which means from stone j mod m to stone (j+ai) mod m (since all stones lie on a circle).
All frogs start their jump at stone 0 , then each of them can jump as many steps as he wants. A frog will occupy a stone when he reach it, and he will keep jumping to occupy as much stones as possible. A stone is still considered ``occupied" after a frog jumped away.
They would like to know which stones can be occupied by at least one of them. Since there may be too many stones, the frogs only want to know the sum of those stones' identifiers.
Input
There are multiple test cases (no more than
20
), and the first line contains an integer
t
,
meaning the total number of test cases.
For each test case, the first line contains two positive integer n and m - the number of frogs and stones respectively (1≤n≤104, 1≤m≤109) .
The second line contains n integers a1,a2,⋯,an , where ai denotes step length of the i -th frog (1≤ai≤109) .
meaning the total number of test cases.
For each test case, the first line contains two positive integer n and m - the number of frogs and stones respectively (1≤n≤104, 1≤m≤109) .
The second line contains n integers a1,a2,⋯,an , where ai denotes step length of the i -th frog (1≤ai≤109) .
Output
For each test case, you should print first the identifier of the test case and then the sum of all occupied stones' identifiers.
Sample Input
3 2 12 9 10 3 60 22 33 66 9 96 81 40 48 32 64 16 96 42 72
Sample Output
Case #1: 42 Case #2: 1170 Case #3: 1872
Source
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5514
题意:n只青蛙在一个长为m的环上跳,第i只青蛙每次跳a[i]步,问这个环上所有能被跳刀的位置的和是多少。
比如 一只青蛙 环长为6 这只青蛙每次跳2步,那么答案就是 2+4+6=12。
思路:首先,容易得到:对于第i只青蛙,它能跳到的位置是gcd(a[i],m)的倍数。
然后计算每个青蛙对答案的贡献(k*gcd(a[i],m)<=m),如果有算重的部分去掉就好。
可是由于m太大,这样写了一发会T。
所以就把m分解因数,然后对每个因数暴力就好了。
算重的部分用容斥原理来处理。
//http://acm.hdu.edu.cn/showproblem.php?pid=5037
#include"stdafx.h"
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define LL long long
#define maxn 120010
using namespace std;
int nk[maxn];
int vis[maxn];
int num[maxn];
int n, m;
int gcd(int a, int b) {
return b ? gcd(b, a%b) : a;
}
int yin[maxn];
int main()
{
int T, k;
scanf("%d", &T);
for (int test = 1;test <= T;test++)
{
memset(yin, 0, sizeof(yin));
memset(num, 0, sizeof(num));
memset(vis, 0, sizeof(vis));
int tmp = 0;
scanf("%d%d", &n, &m);
for (int i = 1;i*i <= m;i++)
{
if (m%i == 0)
yin[tmp++] = i;
if (m%i == 0 && i*i != m)
yin[tmp++] = m / i;
}
sort(yin, yin + tmp);
for (int i = 1;i <= n;i++)
{
scanf("%d", &k);
nk[i] = gcd(k, m);
for (int j = 0;j < tmp;j++)
if (yin[j] % nk[i] == 0)
vis[j] = 1;
}
vis[tmp - 1] = 0;
LL ans = 0;
for (int i = 0; i < tmp; i++)
{
if (vis[i] != num[i])
{
int t = (m - 1) / yin[i];
ans += (long long)t*(t + 1) / 2 * yin[i] * (vis[i] - num[i]);
t = vis[i] - num[i];
for (int j = i; j < tmp; j++)
if (yin[j] % yin[i] == 0)
num[j] += t;
}
}
printf("Case #%d: %lld\n", test, ans);
}
}

本文探讨了n只青蛙在一个长度为m的环上跳跃的问题,每只青蛙有固定的跳跃步长,目标是找出所有能被跳跃到达的位置之和。通过分解m的因数,并利用容斥原理去除重复计算部分,提出了一种高效的算法解决方案。
316

被折叠的 条评论
为什么被折叠?



