hdu 5514 Frogs(容斥)

Frogs

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1315    Accepted Submission(s): 443

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.

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).

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

/*
hdu 5514 Frogs(容斥)

problem:
有n只青蛙和围成一个圈的m个石头. 每只青蛙可以跳a[i]步. 求所有被占领过的石头的编号和

solve:
可以发现青蛙会经过 GCD(a[i],m)的倍数的点.但是有很多重复跳过的石头. 所以会想到容斥.
如果暴力肯定要GG.   可以发现青蛙只会经过gcd(x,m)的点,也就是m的因子.
所以可以把枚举m改成枚举m的因子.  然后利用容斥减去重复的就行.  

hhh-2016-08-30 16:30:55
*/
#pragma comment(linker,"/STACK:124000000,124000000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <math.h>
#include <queue>
#include <set>
#include <map>
#define lson  i<<1
#define rson  i<<1|1
#define ll long long
#define clr(a,b) memset(a,b,sizeof(a))
#define scanfi(a) scanf("%d",&a)
#define scanfs(a) scanf("%s",a)
#define scanfl(a) scanf("%I64d",&a)
#define key_val ch[ch[root][1]][0]
#define inf 1e9
using namespace std;
const ll mod = 1e9+7;
const int maxn = 20005;
int fac[maxn];
int fcnt;
int vis[maxn],hac[maxn];

int gcd(int a,int b)
{
    return b ? gcd(b,a%b) : a;
}

int main()
{
    int T,n,m;
//    freopen("in.txt","r",stdin);
    scanfi(T);
    int cas = 1;
    while(T--)
    {
        scanfi(n),scanfi(m);
        fcnt = 0;
        for(int i = 1;i*i <= m;i++)
        {
            if(m % i == 0)
            {
                fac[fcnt++] = i;
                if(i *i != m)
                    fac[fcnt ++ ] = m/i;
            }
        }
        sort(fac,fac+fcnt);
//        for(int i = 0;i < fcnt;i++)
//            cout << fac[i] <<" ";
//        cout <<endl;
        int x;
        clr(vis,0),clr(hac,0);
        for(int i = 1;i <= n;i++)             //处理会经过哪些因子
        {
            scanfi(x);
            x = gcd(x,m);
            for(int j = 0;j < fcnt;j++)
            {
                if(fac[j] % x== 0)
                    vis[j] = 1;
            }
        }
        vis[fcnt-1] = 0;
        ll ans = 0;
        for(int i = 0;i < fcnt;i++)
        {
            if(vis[i] != hac[i])
            {
                int t = (m-1)/fac[i];
                ans += (ll)t*(t+1)/2 * fac[i] * (vis[i] - hac[i]);         //容斥原理. vis应该计算次数,hac已经计算次数
                t =  (vis[i] - hac[i]);
                for(int j = 0;j < fcnt;j++)
                {
                    if(fac[j] % fac[i] == 0)
                        hac[j] +=   t;
                }
            }
        }
        printf("Case #%d: %I64d\n",cas++,ans);
    }
    return 0;
}

  

时间: 2024-08-17 21:16:55

hdu 5514 Frogs(容斥)的相关文章

hdu 5514 Frogs 容斥思想+gcd 银牌题

Frogs Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1509    Accepted Submission(s): 498 Problem Description There are m stones lying on a circle, and n frogs are jumping over them.The stones a

Hdu 5514 Frogs (容斥原理)

题目链接: Hdu 5514 Frogs 题目描述: 有n只青蛙,m个石头(围成圆圈).第i只青蛙每次只能条ai个石头,问最后所有青蛙跳过的石头的下标总和是多少? 解题思路: 第一反应就是容斥,也是没谁了.但是重现赛的时候并没有做出来,自己写了一个容斥然后挂掉了,今天看到大神的方法,感觉这种处理方法有点神!(还是见的题目太少,太弱了) 第i只青蛙只能走到gcd(ai, m)的位置,我们就可以把m的因子提取出来,然后对青蛙能走到的因子位置打标记.青蛙能走到vis[i]因子位置就把vis[i]标记为

HDU 5213 分块 容斥

给出n个数,给出m个询问,询问 区间[l,r] [u,v],在两个区间内分别取一个数,两个的和为k的对数数量. $k<=2*N$,$n <= 30000$ 发现可以容斥简化一个询问.一个询问的答案为 $[l,v]+(r,u)-[l,u)-(r,v]$,那么我们离线询问,将一个询问分成四个,分块暴力就行了. 然后就是注意细节,不要发生越界,访问错位置之类比较蠢的问题了. /** @Date : 2017-09-24 19:54:55 * @FileName: HDU 5213 分块 容斥.cpp

HDU 5514 Frogs

Frogs Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on HDU. Original ID: 551464-bit integer IO format: %I64d      Java class name: Main There are m stones lying on a circle, and n frogs are jumping over them.The stones are numb

hdu 5212 反向容斥或者莫比

http://acm.hdu.edu.cn/showproblem.php?pid=5212 题意:忽略.. 题解:把题目转化为求每个gcd的贡献.(http://www.cnblogs.com/z1141000271/p/7419717.html 和这题类似 反向容斥)这里先用容斥写了,mobious的之后再说吧23333. 然后比较想说的是这个调和级数的复杂度 nlog(n) ac代码: #include <iostream> #include <cstdio> #includ

HDU 6053 TrickGCD 容斥

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=6053 题意: 给你序列a,让你构造序列b,要求 1<=b[i]<=a[i],且b序列的gcd>=2.问你方案数. 思路: 容易想到的就是我们枚举整个序列的gcd,然后a[i]/gcd就是i位置能够填的数的个数,然后每个位置累积就能得到数列为gcd时的方案数. 最后容斥一下累加就是答案.但是最大gcd可以是100000和明显这样做n^2,会超时. 那么我们把a[i]/gcd的放在一起,然后用

hdu 4407 Sum 容斥+离线

求X-Y之间和p互质的数的和,典型的容斥问题,求和用等差数列求和,注意首项末项是多少. 首先记录下不修改的答案,离线处理,存下询问,输出的时候,遇到一个操作1,就遍历前面的操作,把修改加上去,注意要判重,只保留最后一次修改. #include <stdio.h> #include <vector> #include <algorithm> #include <cmath> #include <iostream> #include<cstri

HDU 1695 GCD(容斥 or 莫比乌斯反演)

这题可以用容斥做,然而效率并不高.. 于是学了下莫比乌斯反演(资料百度找) 求出mo数组后 设f(x)为gcd为x的种数 F(x)为gcd为x倍数的种数 那么显然F(x) = (b / x) * (d / x) 莫比乌斯反演之后,得到f(x) = sum(mo[i] * F(i)). 然后还要容斥减去对称重复的.对称重复的情况为min(b, d)小的中,求一遍除2,(因为存在x = y的情况只有(1,1)一种) 最后还要注意特判下k == 0的情况 代码: #include <cstdio>

HDU 4135 Co-prime (容斥+分解质因子)

<题目链接> 题目大意: 给定区间[A,B](1 <= A <= B <= 10 15)和N(1 <=N <= 10 9),求出该区间中与N互质的数的个数. 解题分析: 将求区间[A,B]与N互质的数转化成求[1,B] 区间与N互质的个数  -  [1,A-1]中与N互质的个数.同时,因为直接求区间内与N互质的数不好求,我们从反面入手,求出与N不互质的数,借鉴埃筛的思想,我们先求出N的所有质因子,然后将这些质因子在区间内倍数的个数全部求出(即与N不互质的数),再用