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 ...
随机推荐
- Hive分组后取组内排名方法row_number
今天遇到这样一个需求场景,要取出 每一种分类(a,b组合分类) 符合条件的日期(字段c) 距离现在最近的10个日期 的数据 首先想到的是用sql筛选出符合某种条件的所有数据,这样的事情很简单 然后用脚 ...
- shell脚本实现轮询查看进程是否结束
功能需求: 一个shell脚本,为了使用多进程,启动十几个后台运行的程序,为了防止脚本比后台进程提前结束造成不可预估的影响,现要判断是否多个后台执行的已知进程已经结束,并在所有进程结束后做出相应操作. ...
- springboot-部署到centos7
环境 系统:centos7 64位 安装jdk 第一步:下载 先进入官网:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-do ...
- 实现自己的Promise polyfill
功能清单: Promise.prototype.then() Promise.prototype.catch() Promise.reject() Promise.resolve() Promise. ...
- String作为输出型参数时获取不到值
有时候在一个方法中,我们需要返回多个字符串,而又不想将这些字段包成一个类.此时就需要使用输出型参数. 但是如果将输出型参数的类型声明为String,那么调用该方法后,是获取不到我们想要的值的. 测试代 ...
- 【Android】Android之Copy and Paste
Android为复制粘贴提供了一个强大的基于剪切板的框架,它支持简单和复杂的数据类型,包括纯文本,复杂的数据结构,二进制流,甚至app资源文件.简单的文本数据直接存储在剪切板中,而复杂的数据则存储的是 ...
- 「6月雅礼集训 2017 Day8」gcd
[题目大意] 定义times(a, b)表示用辗转相除计算a和b的最大公约数所需步骤. 那么有: 1. times(a, b) = times(b, a) 2. times(a, 0) = 0 3. ...
- python模块 zipfile
zipfile是python里用来做zip格式编码的压缩和解压缩的,由于是很常见的zip格式,所以这个模块使用频率也是比较高的zipfile里有两个非常重要的class, 分别是ZipFile和Zip ...
- Ubuntu 14.04 ThinkPad E431无线网卡驱动安装
Ubuntu 14.04下安装无线网卡驱动. sudo apt-get install linux-headers-generic build-essential dkms sudo apt-get ...
- Linux 入门记录:一、命令行 Bash 的基本操作
为了以后长期的线上测试和服务器的性能考量,要用 Linux 服务器了.昨晚装了个 CentOS 6.9,今天开始学学 Linux 基础,扫扫盲.ok,小本本记 ing... 一.Shell简介 She ...