CF1499D The Number of Pairs

首先由裴蜀定理可得 对于方程 lcm(a,b)*c+gcd(a,b)*(-d)=x , x必定是gcd(gcd(a,b),lcm(a,b))的倍数 

显然gcd(gcd(a,b),lcm(a,b))=gcd(a,b) 之后可以在根号x的时间内枚举x的约数作为gcd(a,b)

由于c,d,x,都是给定的,那么lcm(a,b)也能直接求出来

那么问题就转化成了给定lcm(a,b),gcd(a,b),求有多少对a,b

注意到t<=1e4,c,d,x<=1e7,之前枚举约数就已经用了根号x的时间复杂度,这使得求a,b的过程必须在O(1)的限定下完成


对于枚举出来的gcd(a,b)记为G,求得的lcm(a,b)记为L

首先把L不是G的倍数的情况排除掉,因为L一定是G的倍数

由于已经知道了L和G,根据算术基本定理:

a=p1^a1 * p2^a2 *...* pk^ak

b=p1^b1 * p2^b2 *...* pk^bk

(其中p1,p2...pk为2,3,5...等质数,ai,bi>=0)

根据lcm和gcd的定义,就很容易知道max{a1,b1},max{a2,b2}...max{ak,bk}和min{a1,b1},min{a2,b2}...min{ak,bk}

由于只有a,b两个数,对于ai,bi只有两种取值情况:

要么ai=max{ai,bi},bi=min{ai,bi} 要么ai=min{ai,bi},bi=max{ai,bi}

有一种情况例外 就是ai=bi的时候 只有一种取值情况

这里总结一下 对于每个质因数,只有L和G在这个质数上的指数不同时,需要对答案乘以2


为了方便操作 我们可以用lg=L/G 这样对于一对L和G 所贡献的答案为 2^cnt(lg)  其中cnt为lg的质因数的种数 (如:cnt(30)=3 因为30=2*3*5)

到这里问题的关键就是如何O(1)的使用这个cnt函数

本蒟蒻就是卡在这里了,卡了我一个小时也没整出来  cf上分大失败


这时候就需要借助Eratosthenes筛法的思想了

回想一下埃氏筛法 对于质数x,它的倍数2x,3x...一定不是质数

所以在标记2x,3x..不是质数的同时 可以让cnt[2x]++,cnt[3x]++,这就代表了它们包含了x这个质数

而对于没被标记的数就是质数,令它们的cnt=1即可

所以可以在O(NloglogN)的时间复杂度完成对cnt函数的预处理 计算时O(1)调用即可 

貌似lg最大可以取到2e7这个范围


蒟蒻考试时完全忘记了这个东西还在用线性筛傻乎乎地推上不了分惹呜呜呜

下面是题外话:

不得不说莫斯科的作息时间对与中国人是真的阴间,我刚开始比赛时自习室坐着一堆卷王,结束后一回头人全没了。。。 把卷王都给卷没了233333


然额我两点多才睡着的,第二天起来上课困得要死

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define db double
#define rep(x,a,b) for(int x=(a);x<=(b);x++)
#define per(x,a,b) for(int x=(a);x>=(b);x--)
#define scf(a) scanf("%d",&a)
#define scfll(a) scanf("%lld",&a)
#define scfdb(a) scanf("%lf",&a)
#define ptf(a) printf("%d",a)
#define ptfll(a) printf("%lld",a)
#define ptfdb(x,a) printf("%x.lf",a)
#define ptfsp(a) printf("%d ",a)
#define ptfllsp(a) printf("%lld ",a)
#define ptfdbsp(x,a) printf("%x.lf ",a)
#define pli(a,b) make_pair(a,b)
#define pb push_back
#define el puts("")
#define pi 3.1415926
using namespace std;
const ll mod=998244353;
const int maxn=2e5+5;
int cnt[20000005];
ll pw(ll a,ll n){
    ll ans=1,base=a;
    while(n){
        if(n&1) ans=(ans*base);
        base=(base*base);
        n>>=1;
    }
    return ans;
}
ll solve(ll gcdd,ll lcmm){
    if(lcmm%gcdd) return 0;
    ll nx=lcmm/gcdd;
    return pw(2,cnt[nx]);
}
int main(){
    rep(i,2,20000000){
        if(cnt[i]) continue;
        for(int j=i;j<=20000000;j+=i)
            cnt[j]++;
    }
    int T;scf(T);
    while(T--){
        ll c,d,x;
        scfll(c);scfll(d);scfll(x);
        ll ans=0;
        for(ll i=1;i*i<=x;i++){
            ll gcdd,lcmm;
            if(x%i) continue;
            gcdd=x/i;
            if((x+d*gcdd)%c==0){
                lcmm=(x+d*gcdd)/c;
                ans=ans+solve(gcdd,lcmm);
            }
            if(i!=x/i){
                gcdd=i;
                if((x+d*gcdd)%c==0){
                    lcmm=(x+d*gcdd)/c;
                    ans=ans+solve(gcdd,lcmm);
                }
            }
        }
        ptfll(ans);el;
    }
}

猜你喜欢

转载自blog.csdn.net/ghu99999/article/details/115006433