• 数论 + 容斥


    problem's Link

    mean

    给定五个数a,b,c,d,k,从1~a中选一个数x,1~b中选一个数y,使得gcd(x,y)=k.

    求满足条件的pair(x,y)数.

    analyse

    由于b,d,k都是1e5数量级的,普通枚举必定超时.

    首先可以把b,d都同时除以k,问题就转化成了求1~b/k和1~d/k中的gcd(i,j)=k的对数.

    证明如下:

    令Ai∈{1,2,3...b},Bi∈{1,2,3...d}.

    如果有:GCD(Ai,Bi)=k

    则有:GCD(Ai/k,Bi/k)=1

    而对于不能够被k整除的数,不可能有GCD(Ai,Bi)=k.

    也就是说,除以K所剔除掉的数都是不满足条件的数,对最终答案没有影响.

    这样就大大优化了时间复杂度.

    然后就是对1e5以内的数进行质因数分解,使用质因数来构造容斥表.

    再枚举1~b/k之间的每一个数,利用容斥原理算出1~d/k中有多少个数与之互质即可.

    time complexity

    O(N*logN)

    code

    /*
    * this code is made by crazyacking
    * Verdict: Accepted
    * Submission Date: 2015-10-08-21.45
    * Time: 0MS
    * Memory: 137KB
    */
    #include <queue>
    #include <cstdio>
    #include <set>
    #include <string>
    #include <stack>
    #include <cmath>
    #include <climits>
    #include <map>
    #include <cstdlib>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    #define max(a,b) (a>b?a:b)
    using namespace std;
    typedef long long(LL);
    typedef unsigned long long(ULL);
    const double eps(1e-8);
    
    const int NN=100010;
    bool v[NN];
    int p[NN];
    void makePrime()
    {
         int num=-1,i,j;
         for(i=2; i<NN; ++i)
         {
               if(!v[i]) { p[++num]=i; }
               for(j=0; j<=num && i*p[j]<NN; ++j)
               {
                     v[i*p[j]]=true;
                     if(i%p[j]==0) { break; }
               }
         }
    }
    
    struct node
    {
         int fac;
         bool ti;
         node() {}
         node(int a,bool b):fac(a),ti(b) {}
    };
    vector<node> pa[NN];
    
    void pre()
    {
         int i,j,a,cnt,si;
         for(i=1; i<=100000; ++i)
         {
               a=i;
               cnt=0;
               for(j=0; j<=9672; ++j)
               {
                     if(!(a%p[j]))
                     {
                           pa[i].push_back(node(p[j],false));
                           si=pa[i].size();
                           for(int k=0; k<si-1; ++k)
                           {
                                 pa[i].push_back(node(pa[i][si-1].fac*pa[i][k].fac,!pa[i][k].ti));
                           }
                           while(!(a%p[j]))
                                 a/=p[j];
                     }
                     if(p[j]>a || a<=0) break;
               }
         }
    }
    
    
    int main()
    {
         makePrime();
         pre();
         ios_base::sync_with_stdio(false);
         cin.tie(0);
         int t;
         scanf("%d",&t);
         for(int Cas=1; Cas<=t; ++Cas)
         {
               int a,b,c,d,k,si;
               scanf("%d %d %d %d %d",&a,&b,&c,&d,&k);
               if(k==0)
               {
                     printf("Case %d: 0
    ",Cas);
                     continue;
               }
               a=b/k;
               b=d/k;
               if(a>b) swap(a,b);
               LL ans=b;
               if(a==0) ans=0;
               for(int i=2; i<=a; ++i)
               {
                     si=pa[i].size();
                     for(int j=0; j<si; ++j)
                     {
                           if(!(pa[i][j].ti))
                           {
                                 ans+=((b-i+1)-b/pa[i][j].fac+(i-1)/pa[i][j].fac);
                           }
                           else
                           {
                                 ans-=((b-i+1)-b/pa[i][j].fac+(i-1)/pa[i][j].fac);
                           }
                     }
               }
               printf("Case %d: %I64d
    ", Cas, ans);
         }
         return 0;
    }
  • 相关阅读:
    阻止事件冒泡和默认行为,禁止键盘事件
    jquery移除、绑定、触发元素事件
    HTML`CSS_网站页面不同浏览器兼容性问题解决
    computed属性与methods、watched
    call()方法和apply()方法用法总结
    push()、shift()与pop()、unshift()、splice()
    vue指令总结
    fieldset标签
    mysql存储过程定义者
    数据库死锁
  • 原文地址:https://www.cnblogs.com/crazyacking/p/4864980.html
Copyright © 2020-2023  润新知