hdu 4135 Co-prime 【容斥定理應用】
阿新 • • 發佈:2018-12-07
題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=4135
容斥定理求一個區間內與n互素的數有幾個;
和模板差不多,只是區間 [1,R] 變成 [L,R],所以可以求出 [1,L] 和 [1,R] 的互素的數的shu'lian再相減,注意這道題的範圍;
關於容斥定理的詳解 我推薦這篇部落格:https://blog.csdn.net/m0_37286282/article/details/78869512#t6)
先給出模板:
int solve (int n, int r) { vector<int> p; for (int i=2; i*i<=n; ++i) if (n % i == 0) { p.push_back (i); while (n % i == 0) n /= i; } if (n > 1) p.push_back (n); int sum = 0; for (int msk=1; msk<(1<<p.size()); ++msk) { int mult = 1, bits = 0; for (int i=0; i<(int)p.size(); ++i) if (msk & (1<<i)) { ++bits; mult *= p[i]; } int cur = r / mult; if (bits % 2 == 1) sum += cur; else sum -= cur; } return r - sum; }
這是AC程式碼:
#include<stdio.h> #include<string.h> #include<string> #include<queue> #include<stack> #include<map> #include<vector> #include<set> #include<algorithm> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int N=1e5+10; vector<ll>p; ll solve(ll l,ll r,ll n) { p.clear(); for(ll i=2;i*i<=n;i++) { if(n%i==0) { p.push_back(i); while(n%i==0) n/=i; } } if(n>1) p.push_back(n); ll suma=0,sumb=0; for(int i=1;i<(1<<p.size());++i) { ll k=0; ll pa=1,pb=1; for(int j=0;j<p.size();++j) { if(i&(1<<j)) { k++; pa*=p[j]; pb*=p[j]; } } pa=l/pa; pb=r/pb; if(k%2==1) suma+=pa,sumb+=pb; else suma-=pa,sumb-=pb; } return sumb-suma; } int main() { int T,cal=0; scanf("%d",&T); while(T--) { ll l,r,n; scanf("%lld %lld %lld",&l,&r,&n); l--; printf("Case #%d: %lld\n",++cal,r-l-solve(l,r,n)); } return 0; }