zoukankan      html  css  js  c++  java
  • 牛客练习赛44 C 小y的质数 (数论,容斥定理)

    链接:https://ac.nowcoder.com/acm/contest/634/C
    来源:牛客网

    题目描述
    给出一个区间[L,R],求出[L,R]中孪生质数有多少对。
    由于这是一个区间筛质数的模板题。所以小k不屑于去写。
    所以出题人只好yy了另一道题。
    定义k生互质数为满足y + k与y - k互质的数。
    现在给出区间[L,R],你需要输出区间内k生互质数有多少对
    我们说一对k生互质数在区间[L,R]内,当且仅当y+k in[L,R]y+k∈[L,R]且y-k in[L,R]y−k∈[L,R]
    输入描述:
    一行三个数字L,R,k
    输出描述:
    一行一个数字表示区间[L,R]内的k生互质数的对数
    示例1
    输入
    复制
    5 10 1
    输出
    复制
    2
    说明
    分别为(5,7),(7,9)
    示例2
    输入
    复制
    287 11633 10
    输出
    复制
    4532
    备注:
    0 leq L,R leq 10^{18}0≤L,R≤10
    18

    1 leq k leq 10^{13}1≤k≤10
    13

    思路:
    题意为让你寻找 L 到 R 中 多少 x 使 gcd(x-k,x+k)=1

    根据gcd的性质,我们可以得到 gcd(x,x+2 * k ) =1

    即 gcd(x,2k)=1

    有因为 题目要求 x+k 小于R

    所以 题目可以转化为 l~r-2k 中,有多少个数 x 使得 gcd(x, 2k)==1

    这就是一个景点的问题了。

    即:

    对 2 * k 进行素数分解,[l,r] 所有gcd > 1的数字集合中 可能包括 i 种和 2 * k 相同的素因子,枚举一下用容斥原理扣掉,先扣掉包括一种 相同素因子的数的个数, 然后加上 包括 两种相同素因子的数的个数。。。。一路搞到包括所有素因子(容斥原理)。至于有多少个数包含这些数因子,除一下就知道了。

    两个细节:

    r-2k后可以小于l

    l可以为0 要判断 l-1 和0的大小关系。

    细节见代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <vector>
    #include <iomanip>
    #define ALL(x) (x).begin(), (x).end()
    #define sz(a) int(a.size())
    #define all(a) a.begin(), a.end()
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define gg(x) getInt(&x)
    #define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
    using namespace std;
    typedef long long ll;
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
    ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;}
    inline void getInt(int* p);
    const int maxn = 1000010;
    const int inf = 0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    
    std::vector<ll> v;
    void breakdown(ll x)
    {
        for(ll i=2ll;i*i<=x;++i)
        {
            int cnt=0;
            while(x%i==0)
            {
                cnt++;
                x/=i;
            }
            if(cnt)
            {
                v.push_back(i);
            }
        }
        if(x>1)
        {
            v.pb(x);
        }
    }
    ll l,r,k;
    int main()
    {
        //freopen("D:\code\text\input.txt","r",stdin);
        //freopen("D:\code\text\output.txt","w",stdout);
        gbtb;
        cin>>l>>r>>k;
        k<<=1;
        r-=k;
        if(l>r)
        {
            cout<<0<<endl;
            return 0;
        }
        breakdown(k);
        int len=sz(v);
        int maxstate=(1<<len)-1;
        ll ans=0ll;
        l=max(l-1ll,0ll);
        for(int i=0;i<=maxstate;++i)
        {
            int num=0;
            ll p=1ll;
            for(int j=0;j<len;++j)
            {
                if(i&(1<<j))
                {
                    num++;
                    p*=v[j];
                }
            }
    //        cout<<(r/p-l/p)<<" "<<num<<endl;
            ans+=(r/p-l/p)*((num&1)?-1ll:1ll);
        }
        cout<<ans<<endl;
        return 0;
    }
    
    inline void getInt(int* p) {
        char ch;
        do {
            ch = getchar();
        } while (ch == ' ' || ch == '
    ');
        if (ch == '-') {
            *p = -(getchar() - '0');
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 - ch + '0';
            }
        }
        else {
            *p = ch - '0';
            while ((ch = getchar()) >= '0' && ch <= '9') {
                *p = *p * 10 + ch - '0';
            }
        }
    }
    
    
    
    
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    vtk类之vtkTextSource:显示一个文本的poly data
    vtk类之vtkRotationalExtrusionFilter:建模筛选器, 它采用多边形数据作为输入,并生成输出的多边形数据
    vtk类之vtkTransform 和 vtkTransformFilter:对可视化管线中的点坐标进行齐次坐标转换
    vtk类之vtkShrinkFilter :收缩构成对其质心任意数据集的单元格,返回vtkUnstructuredGrid数据集
    wxPython控件学习之UltimateListCtrl空间中使用ComboBox时,该控件一直在重绘的问题
    vtk类之vtkPointSource:创建一些点集合围成的球体poly data
    vtk类之vtkPlaneSource:创建一个平面的poly data
    vtk类之vtkSuperquadricSource:创建以原点为中心的多边形超二次曲面的poly data
    vtk类之vtkOutlineSource:创建边界盒状或者带弧度角度的poly data
    中国天气网的中央气象台实时数据接口
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/11348842.html
Copyright © 2011-2022 走看看