HDU 5514.Frogs-欧拉函数 or 容斥原理
Frogs
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 4904 Accepted Submission(s): 1631
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.
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).
2 12
9 10
3 60
22 33 66
9 96
81 40 48 32 64 16 96 42 72
Case #2: 1170
Case #3: 1872
题意就是跳青蛙,通过分析会发现,就是步数a[i]与石头数m,通过gcd(a[i],m)之后,gcd的倍数的和。
因为重复的数只计算一次,所以要去重。
一开始想的是容斥去重,然而还是太捞了,。。。
这道题和队友讨论了3天,还问了学长,发现几个问题:
(1)如果直接枚举gcd的遍历,应该为去重他们的最小公倍数,也就是这样的。
for(ll j=;j<cnt;j++)
{
if(i&(<<j))
temp=temp*g[j]/gcd(temp,g[i]),jishu++;
}
(2)直接gcd的容斥枚举去重会超时,因为极限数据可能要枚举1<<36次,for一次的极限数据个人认为可能就是1e7再带点常数,1<<36次跑不出来,程序会崩。所以这种容斥是不可以的,虽然想法真的很好,但是真的过不去。所以,最后放弃了这种思路,其实还是可以容斥的,但是是有技巧的容斥。
直接看的题解,所以也不好说什么,毕竟是人家的劳动成果,只是分析一下。
做法一:
欧拉函数的延伸用法:小于或等于n的数中,与n互质的数的总和为:φ(n) * n / 2 (n>1)。
做法二:
枚举m的因子个数,这样就会少很多,就不存在超时的问题了。
以上两种做法的具体题解传送门:HDU 5514 Frogs(欧拉函数+数论YY)
直接贴代码吧。
代码1(欧拉函数):
//欧拉函数的公式求解
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii; const double PI=acos(-1.0);
const double eps=1e-;
const ll mod=1e9+;
const int inf=0x3f3f3f3f;
const int maxn=1e5+;
const int maxm=+;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); ll a[maxn],n,m; ll gcd(ll a,ll b)
{
return b==?a:gcd(b,a%b);
} ll euler(ll n)
{
ll ans=n;
for(int i=;i*i<=n;i++){
if(n%i==){
ans=ans/i*(i-);
while(n%i==) n/=i;
}
}
if(n>) ans=ans/n*(n-);
return ans;
} bool solve(int x)
{
for(int i=;i<n;i++){
if(x%a[i]==) return true;
}
return false;
} int main()
{
int t;
scanf("%d",&t);
for(int cas=;cas<=t;cas++){
memset(a,,sizeof(a));
scanf("%lld%lld",&n,&m);
for(int i=;i<n;i++){
scanf("%d",a+i);
a[i]=gcd(a[i],m);
}
ll ans=;
for(int i=;i*i<=m;i++){
if(m%i) continue;
if(solve(i)) ans+=(ll)euler(m/i)*m/;
if(i*i==m||i==) continue;
if(solve((m/i))) ans+=(ll)euler(i)*m/;
}
printf("Case #%d: %lld\n",cas,ans);
}
}
代码2(容斥原理):
//容斥定理
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii; const double PI=acos(-1.0);
const double eps=1e-;
const ll mod=1e9+;
const int inf=0x3f3f3f3f;
const int maxn=1e5+;
const int maxm=+;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); ll gcd(ll a,ll b)
{
return b==?a:gcd(b,a%b);
} ll g[maxn],fac[maxn];
int tp[maxn],num[maxn],vis[maxn]; int main()
{
int t;
scanf("%d",&t);
for(int cas=;cas<=t;cas++){
ll n,m;
scanf("%lld%lld",&n,&m);
int ok=;
for(int i=;i<n;i++){
scanf("%lld",&g[i]);
g[i]=gcd(g[i],m);
if(g[i]==) ok=;
}
if(ok==){
printf("Case #%d: %lld\n",cas,m*(m-)/);
continue;
}
sort(g,g+n);
n=unique(g,g+n)-g;
memset(vis,,sizeof(vis));
memset(num,,sizeof(num));
int cnt=;
for(ll i=;i*i<=m;i++){
if(i*i==m) fac[cnt++]=m/i;
else if(m%i==) fac[cnt++]=i,fac[cnt++]=m/i;
}
sort(fac,fac+cnt);
int cnt1=;
for(int i=;i<n;i++){
if(!vis[i]){
tp[cnt1++]=g[i];
for(int j=;j<n;j++)
if(g[j]%g[i]==) vis[j]=;
}
}
memset(vis,,sizeof(vis));
for(int i=;i<cnt;i++){
for(int j=;j<cnt1;j++){
if(fac[i]%tp[j]==){
vis[i]=;
break;
}
}
}
ll sum=;
for(int i=;i<cnt;i++){
if(num[i]!=vis[i]){
sum+=m*(m/fac[i]-)/*(vis[i]-num[i]);
for(int j=i+;j<cnt;j++)
if(fac[j]%fac[i]==)
num[j]=num[j]+vis[i]-num[i];
}
}
printf("Case #%d: %lld\n",cas,sum);
}
return ;
}
贴一下我们想了3天的错误代码,纪念一下。
代码(错误的):
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii; const double PI=acos(-1.0);
const double eps=1e-;
const ll mod=1e9+;
const int inf=0x3f3f3f3f;
const int maxn=1e5+;
const int maxm=+;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1 ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
} ll sum(ll x,ll n)
{
ll temp=(n-)/x;
return temp*x+(temp*(temp-)/)*x;
} ll a[maxn]; int main()
{
ll t;
scanf("%lld",&t);
for(int cas=;cas<=t;cas++)
{
ll n,m;
scanf("%lld%lld",&n,&m);
ll h=;
for(int i=;i<n;i++)
{
ll x;
scanf("%lld",&x);
a[h++]=gcd(x,m);
}
vector<ll> g;
sort(a,a+h);
for(int i=h-;i>=;i--){
int flag=;
for(int j=i-;j>=;j--){
if(a[i]%a[j]==) flag=;
}
if(!flag) g.push_back(a[i]);
}
int cnt=g.size();
ll ans=;
for(ll i=;i<(1ll<<cnt);i++)
{
ll temp=,jishu=;
for(ll j=;j<cnt;j++)
{
if(i&(<<j))
temp=temp*g[j]/gcd(temp,g[i]),jishu++;
}
if(jishu==)continue;
if(jishu&) ans+=sum(temp,m);
else ans-=sum(temp,m);
}
printf("Case #%d: %lld\n",cas,ans);
}
}
到此为止,拜拜,再也不看这个题了。
HDU 5514.Frogs-欧拉函数 or 容斥原理的更多相关文章
- HDU 5514 Frogs 欧拉函数
题意: 有\(m(1 \leq m \leq 10^9)\)个石子排成一圈,编号分别为\(0,1,2 \cdots m-1\). 现在在\(0\)号石头上有\(n(1 \leq n \leq 10^4 ...
- HDU 1695 GCD (欧拉函数,容斥原理)
GCD Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...
- hdu 1695 GCD (欧拉函数+容斥原理)
GCD Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- hdu 1695 GCD (欧拉函数、容斥原理)
GCD Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...
- HDU 2824 简单欧拉函数
1.HDU 2824 The Euler function 2.链接:http://acm.hdu.edu.cn/showproblem.php?pid=2824 3.总结:欧拉函数 题意:求(a ...
- HDU 1695 GCD 欧拉函数+容斥定理
输入a b c d k求有多少对x y 使得x在a-b区间 y在c-d区间 gcd(x, y) = k 此外a和c一定是1 由于gcd(x, y) == k 将b和d都除以k 题目转化为1到b/k 和 ...
- HDU 1695 GCD 欧拉函数+容斥定理 || 莫比乌斯反演
GCD Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- GuGuFishtion HDU - 6390 (欧拉函数,容斥)
GuGuFishtion \[ Time Limit: 1500 ms\quad Memory Limit: 65536 kB \] 题意 给出定义\(Gu(a, b) = \frac{\phi(ab ...
- HDU 2588 GCD (欧拉函数)
GCD Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u Submit Status De ...
- hdu 6434 Count (欧拉函数)
题目链接 Problem Description Multiple query, for each n, you need to get $$$$$$ \sum_{i=1}^{n} \sum_{j=1 ...
随机推荐
- sql service 事务与锁
了解事务和锁 事务:保持逻辑数据一致性与可恢复性,必不可少的利器. 锁:多用户访问同一数据库资源时,对访问的先后次序权限管理的一种机制,没有他事务或许将会一塌糊涂,不能保证数据的安全正确读写. 死锁: ...
- [技巧篇]01.Servlet的优化模版代码
Servlet.java的模版 #---------------------------------------------# # <aw:description>Template for ...
- Java中xml2json,json2xml
在JAVA中xml与json数据互相转换 package com.sgcc.platform.common.utils; import static java.lang.String.format; ...
- java线程的常用方法和属性介绍
start() start方法是Thread 类的方法,在这个方法中会调用native方法(start0())来启动线程,为该线程分配资源. sleep() sleep方法有2个方法. public ...
- mysql varchar到底能存多少字符。
utf8编码的varchar Mysql记录行数据是有限的.大小为64k,即65535个字节,而varchar要用1-2字节来存储字段长度,小于255的1字节,大于255的2字节. Mysql 5.0 ...
- UVA 11105 Semi-prime H-numbers
https://vjudge.net/problem/UVA-11105 筛法 #include<cstdio> #include<cstring> #define N 100 ...
- [洛谷P2491] [SDOI2011]消防
洛谷题目链接:[SDOI2011]消防 题目描述 某个国家有n个城市,这n个城市中任意两个都连通且有唯一一条路径,每条连通两个城市的道路的长度为zi(zi<=1000). 这个国家的人对火焰有超 ...
- Android蓝牙通信总结
这篇文章要达到的目标: 1.介绍在Android系统上实现蓝牙通信的过程中涉及到的概念. 2.在android系统上实现蓝牙通信的步骤. 3.在代码实现上的考虑. 4.例子代码实现(手持设备和蓝牙串口 ...
- bzoj 1774: [Usaco2009 Dec]Toll 过路费 ——(改)floyd
Description 跟所有人一样,农夫约翰以着宁教我负天下牛,休叫天下牛负我的伟大精神,日日夜夜苦思生 财之道.为了发财,他设置了一系列的规章制度,使得任何一只奶牛在农场中的道路行走,都 要向农夫 ...
- 【51NOD-0】1118 机器人走方格
[算法]DP #include<cstdio> #include<algorithm> using namespace std; ,maxn=; int f[maxn][max ...