HDU 5514 Frogs(容斥)
2016-09-08 16:41
363 查看
给你n个步长,圈长m,从0到m−1
然后问你这n个步长,能走到那些位置,求位置之和
gcd(a[i],m)=k[i],说明第i个步长,能走m/k个位置
然后会有重复计算,那么就需要容斥,但是n有1W,不好直接容斥
该怎么办呢,考虑m的因子,比如有tot个因子
如果k[i]是一些因子的倍数,那么说明这些因子的步长都会被走过
所以可以考虑,每个因子,应该走几次vis[j],已经被走了几次num[j]
这个已经被走是什么概念,就是它的因子走一次,说明它也走了一次
所以可以O(num2因子)的复杂度解决
比如对于因子6,如果原本的步长里有2
那么它应该走1次,因为有因子6的话,肯定有2和3
那么2也应该走一次,6就被走了一次,3没有走,所以6应该走一次,已经被走1次,所以6算0次
如果步长里还有3,那么6应该走1次,已经被走2次,就要算−1次,减去
讲道理这种方法很巧妙,我还是太弱了,想到了因子2的复杂度,还是没做出来
代码:
然后问你这n个步长,能走到那些位置,求位置之和
gcd(a[i],m)=k[i],说明第i个步长,能走m/k个位置
然后会有重复计算,那么就需要容斥,但是n有1W,不好直接容斥
该怎么办呢,考虑m的因子,比如有tot个因子
如果k[i]是一些因子的倍数,那么说明这些因子的步长都会被走过
所以可以考虑,每个因子,应该走几次vis[j],已经被走了几次num[j]
这个已经被走是什么概念,就是它的因子走一次,说明它也走了一次
所以可以O(num2因子)的复杂度解决
比如对于因子6,如果原本的步长里有2
那么它应该走1次,因为有因子6的话,肯定有2和3
那么2也应该走一次,6就被走了一次,3没有走,所以6应该走一次,已经被走1次,所以6算0次
如果步长里还有3,那么6应该走1次,已经被走2次,就要算−1次,减去
讲道理这种方法很巧妙,我还是太弱了,想到了因子2的复杂度,还是没做出来
代码:
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; #define MAX 10005 #define MAXN 1000005 #define maxnode 205 #define sigma_size 2 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lrt rt<<1 #define rrt rt<<1|1 #define middle int m=(r+l)>>1 #define LL long long #define ull unsigned long long #define mem(x,v) memset(x,v,sizeof(x)) #define lowbit(x) (x&-x) #define pii pair<int,LL> #define bits(a) __builtin_popcount(a) #define mk make_pair #define limit 10000 //const int prime = 999983; const int INF = 0x3f3f3f3f; const LL INFF = 0x3f3f; //const double pi = acos(-1.0); const double inf = 1e18; const double eps = 1e-9; const LL mod = 1e8+9; const ull mx = 133333331; /*****************************************************/ inline void RI(int &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; } /*****************************************************/ int a[MAX]; int yin[MAX]; int vis[MAX]; int num[MAX]; int gcd(int a,int b){ if(!b) return a; return gcd(b,a%b); } int main(){ int t,kase=0; cin>>t; while(t--){ int n,m; cin>>n>>m; for(int i=0;i<n;i++) scanf("%d",&a[i]); int tot=0; mem(vis,0); mem(num,0); for(int i=1;i<=sqrt(m);i++){ if(m%i==0){ yin[tot++]=i; if(m/i!=i) yin[tot++]=m/i; } } sort(yin,yin+tot); for(int i=0;i<n;i++){ int k=gcd(a[i],m); for(int j=0;j<tot;j++){ if(yin[j]%k==0) vis[j]=1; } } vis[tot-1]=0; LL ans=0; for(int i=0;i<tot;i++){ if(vis[i]!=num[i]){ int x=(m-1)/yin[i]; ans+=(LL)x*(x+1)/2*yin[i]*(vis[i]-num[i]); int y=vis[i]-num[i]; for(int j=i+1;j<tot;j++){ if(yin[j]%yin[i]==0) num[j]+=y; } } } kase++; printf("Case #%d: ",kase); cout<<ans<<endl; } return 0; }
相关文章推荐
- HDU 5514 Frogs(巧妙地容斥)
- hdu 5514 Frogs(容斥)
- HDU - 5514 Frogs (容斥)
- HDU 5514 Frogs(容斥问题)
- HDU 5514 Frogs (数论容斥)
- HDU - 5514 Frogs (2015 ICPC沈阳 容斥)
- HDU Frogs 5514 容斥
- HDU - 5514 - Frogs 【完美使用欧拉函数 -> 也可容斥】
- HDU 5514 Frogs 容斥
- HDU 5514 Frogs(容斥)
- hdu 5514 Frogs 容斥或欧拉函数
- HDU 5514 Frogs (容斥+数论)
- HDU 5514 Frogs 欧拉函数
- HDU 5514 Frogs (容斥定理)
- HDU 5514 Frogs(容斥原理 gcd)
- hdu 5514 Frogs
- HDU 5514 Frogs
- HDU 5514 (ACM 2015 沈阳) Frogs [容斥+记忆化搜索]
- HDU-5514-Frog(容斥)
- HDU 5514 Frogs