[HDU](5514)Frogs ---- 技巧容斥原理★
阿新 • • 發佈:2018-12-13
總結:
- 指數型的容斥一定會超時……TLE到哭
- 無可奈何只好賽後去看了題解,才發現容斥才可這樣寫
- 重點是用vis[i]-num[i]來求m所有因子的對結果貢獻(這個真的是很有技巧的想法)
AC程式碼:
#include<bits/stdc++.h> #define IO ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0) #define pb(x) push_back(x) #define sz(x) (int)(x).size() #define sc(x) scanf("%d",&x) #define pr(x) printf("%d\n",x) #define abs(x) ((x)<0 ? -(x) : x) #define all(x) x.begin(),x.end() #define mk(x,y) make_pair(x,y) #define debug printf("!!!!!!\n") #define fin freopen("in.txt","r",stdin) #define fout freopen("out.txt","w",stdout) using namespace std; typedef long long ll; typedef pair<int,int> PII; const int mod = 1e9+7; const double PI = 4*atan(1.0); const int maxn = 1e5+5; const int maxm = 1e6+5; const int INF = 0x3f3f3f3f; const ll LINF = 1ll<<62; int vis[maxn],num[maxn]; int d[maxn]; int vec[maxn]; int cnt; int gcd(int a,int b){return b?gcd(b,a%b):a;} void dec(int x) { int t = x; cnt = 0; for(int i=1;i*i<=t;i++) { if(t%i == 0){ vec[cnt++] = i; if(i*i!=t) vec[cnt++] = t/i; } } } int main() { // fin; int t; scanf("%d",&t); int n,m,e; for(int ca=1;ca<=t;++ca) { memset(vis,0,sizeof(vis)); memset(num,0,sizeof(num)); scanf("%d %d",&n,&m); for(int i=0;i<n;i++) { scanf("%d",&e); d[i] = gcd(e,m); } dec(m); sort(vec,vec+cnt); for(int i=0;i<n;i++) { for(int j=0;j<cnt;j++) { if(vec[j]%d[i] == 0) vis[j] = 1; } } ll res = 0; for(int i=0;i<cnt-1;i++) { if(vis[i]!=num[i]) { ll tmp = (m-1)/vec[i]; res += tmp*(tmp+1)/2*vec[i]*(vis[i]-num[i]);//帶技巧的容斥 for(int j=i+1;j<cnt;j++) { if(vec[j]%vec[i] == 0) num[j] += (vis[i]-num[i]); } } } printf("Case #%d: %lld\n",ca,res); } return 0; }