zoukankan      html  css  js  c++  java
  • hdu 4135 Co-prime (素数打表+容斥原理)

    题目链接

    题意:问从A到B中与N互素的个数。

    题解:

    利用容斥原理:先求出与n互为素数的个数。

    可以先将 n 进行素因子分解,然后用区间 x 除以 素因子,就得到了与 n 的 约数是那个素因子的个数,然后每次这样求一遍,但是发现有重 复的:举个例子 [1,10] 区间中与 6 互素的个数,应该是 10−(10/2+10/3)+(10/6)
    然后利用二进制枚举子集个数,奇数加偶数减。
    具体看代码:
    #include <stdio.h>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #include <queue>
    #include <map>
    #include <list>
    #include <utility>
    #include <set>
    #include <algorithm>
    #include <deque>
    #include <iomanip>
    #include <vector>
    #define mem(arr, num) memset(arr, 0, sizeof(arr))
    #define _for(i, a, b) for (int i = a; i <= b; i++)
    #define __for(i, a, b) for (int i = a; i >= b; i--)
    #define IO                       
        ios::sync_with_stdio(false); 
        cin.tie(0);                  
        cout.tie(0);
    using namespace std;
    typedef long long ll;
    typedef vector<int> vi;
    const ll INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    const int N = 20 + 5;
    const int maxn = 1000000+5;
    bool vis[maxn+1000000];  
    int fac[maxn/100+5];
    int prime[maxn],n; 
    int num = 0; 
    void getprime()  
     {  
         memset(vis, false, sizeof(vis));  
         for (int i = 2; i <= maxn; ++i)  
         {  
             if ( !vis[i] )  prime[++num] = i;  
             for (int j = 1; j <= num && i * prime[j] <= n;  j++)  
             {  
                 vis[ i  *  prime[j] ]  =  true;  
                 if (i % prime[j] == 0) break;  
             }  
         }  
     }
     int cnt = 0;
     void f(ll x) {
         cnt = 0;
         for(int i = 1; prime[i]*prime[i] <=x && i <=num; i++) {
             if(x%prime[i]==0){
                 fac[++cnt] = prime[i];
                 while(x%prime[i]==0) x /= prime[i];
             }
         }
         if(x > 1) fac[++cnt] = x;
     }
     ll solve(ll x) { //利用二进制处理子集,奇数加偶数减。
         ll ans = 0;
         for(int i = 1; i < ((ll)1 << cnt); i++) {
             int tmp = 1,sum = 0;
             for(int j = 0; j < cnt;j++){
                 if(i&((ll)1<<j))sum++, tmp *= fac[j+1];
             }
             if(sum&1) ans += x/tmp;
             else ans -= x/tmp;
         }
         return ans;
     }
     int main() {
         int T;
         ll ans = 0,A,B,N;
         scanf("%d",&T);
         getprime();
         for(int i = 1; i <= T; i++){
             scanf("%lld%lld%lld",&A,&B,&N);
             f(N);
             ans = B - solve(B) - ((A - 1) - solve(A-1));
             printf("Case #%d: %lld
    ",i,ans);
         }
         return 0;
     }
    宝剑锋从磨砺出 梅花香自苦寒来
  • 相关阅读:
    UVa OJ 148 Anagram checker (回文构词检测)
    UVa OJ 134 LoglanA Logical Language (Loglan逻辑语言)
    平面内两条线段的位置关系(相交)判定与交点求解
    UVa OJ 130 Roman Roulette (罗马轮盘赌)
    UVa OJ 135 No Rectangles (没有矩形)
    混合函数继承方式构造函数
    html5基础(第一天)
    js中substr,substring,indexOf,lastIndexOf,split等的用法
    css的textindent属性实现段落第一行缩进
    普通的css普通的描边字
  • 原文地址:https://www.cnblogs.com/GHzcx/p/8824035.html
Copyright © 2011-2022 走看看