D. The Number of Pairs (Thinking + Number Theory + Euler Sieve/A Si Si)

https://codeforces.com/contest/1499/problem/D


Reference solution:

https://blog.csdn.net/ghu99999/article/details/115006433


Ideas:

First, the sufficient and necessary conditions for the solution of the Pei Shu theorem ax+by=c can be obtained 

For the equation lcm(a,b)*c+gcd(a,b)*(-d)=x, x must be a multiple of gcd(gcd(a,b),lcm(a,b))

Consider gcd(a,b) as the prime factor of a, b and take min, and lcm(a,b) as the prime factor of a, b and take max, you can find that the answer is still gcd(a,b)

Therefore, we can know that gcd(a,b) is a divisor of x. At this time, sqrt can enumerate the value of gcd(a,b). Since c,d, is known, O1 can get lcm(a, b);

At this time, the problem becomes how many pairs of ab that gcd(a,b) and lcm(a,b) are satisfied are already known.

Here is the conclusion part and the comparative thinking part.

Reference: https://blog.csdn.net/qq_36394234/article/details/114994557

 


At this point, 2^nO1 can be used to calculate the answer, but it should be noted that the divisibility of the formula must be satisfied. That is, lcm%c==0, and lcm must be a multiple of gcd.

 

So start the preprocessing part. Normally, we finish the log run by Euler Sieve, n+nlogn. However, I opened LL, which caused tle1 to be confused for a long time. Finally, 1996ms stuck.

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
#define LL int
using namespace std;
const int maxn=2e7+5000;
inline LL read(){LL x=0,f=1;char ch=getchar();	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL primes[1270610],m=0;
LL v[maxn];//[]存每个数的最小质因子
LL num[maxn];
void getprimes(LL n){
	for(int i=2;i<=n;i++){
		if(v[i]==0) {v[i]=i;primes[++m]=i;}
		for(LL j=1;j<=m;j++){
			if(primes[j]>v[i]||primes[j]>n/i)	break;
			v[i*primes[j]]=primes[j];
		}
	}
    for(int i=2;i<=n;i++){
        LL k=i;LL cnt=0;
        while(k>1){
            LL temp=v[k];
            cnt++;
            while(k%temp==0){
                k/=temp;
            }
        }
        if(k>1) cnt++;
        num[i]=cnt;
    }
}
LL add(LL c,LL d,LL x,LL gcd){
    long long int lcm=x+1ll*d*gcd;
    long long int res=0;
    if(lcm%c==0){
        lcm/=c;
        if(lcm%gcd==0){
            res+=(1ll<<num[lcm/gcd]);
        }
    }
    return res;
}
void solve(LL c,LL d,LL x){
   long long int ans=0;
    for(LL i=1;i*i<=x;i++){
        if(x%i==0){
            ans+=add(c,d,x,i);
            if(i*i!=x) ans+=add(c,d,x,x/i);
        }
    }
    printf("%lld\n",ans);
}
int main(void)
{
  getprimes(20000010);
  int T;scanf("%d",&T);
  while(T--){
    LL c,d,x;c=read();d=read();x=read();
    solve(c,d,x);
  }
return 0;
}

 


This is too dangerous. Seeing that everyone else is Essie, isn’t Euler working? It can still be screened out on

Let's look at Euler Sieve again, num[i] is the number of prime factors of i. When i%primes[j]!=0, the update of num[i*primes[j]] comes from a part of num[i] and primes[j].

When i%primes[j[==0, primes[j] itself is contained in num[i]. Therefore num[i*primes[j]=num[i]

Then On ran. 1200ms.

It's still not fast. Is it 1005ms to sieve the cin..

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
#define LL int
using namespace std;
const int maxn=2e7+5000;
inline LL read(){LL x=0,f=1;char ch=getchar();	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL primes[1270610],m=0;
LL v[maxn];//[]存每个数的最小质因子
LL num[maxn];
void getprimes(LL n){
	for(int i=2;i<=n;i++){
		if(v[i]==0) {v[i]=i;primes[++m]=i;num[i]=1;}
		for(LL j=1;j<=m&&primes[j]<=n/i;j++){

			v[i*primes[j]]=primes[j];
			if(i%primes[j]==0){
                num[i*primes[j]]=num[i];
                break;
			}
			num[i*primes[j]]=(1+num[i]);
		}
	}
}
LL add(LL c,LL d,LL x,LL gcd){
    long long int lcm=x+1ll*d*gcd;
    long long int res=0;
    if(lcm%c==0){
        lcm/=c;
        if(lcm%gcd==0){
            res+=(1ll<<num[lcm/gcd]);
        }
    }
    return res;
}
void solve(LL c,LL d,LL x){
   long long int ans=0;
    for(LL i=1;i*i<=x;i++){
        if(x%i==0){
            ans+=add(c,d,x,i);
            if(i*i!=x) ans+=add(c,d,x,x/i);
        }
    }
    printf("%lld\n",ans);
}
int main(void)
{
  getprimes(20000010);
  int T;scanf("%d",&T);
  while(T--){
    LL c,d,x;c=read();d=read();x=read();
    solve(c,d,x);
  }
return 0;
}

 

Guess you like

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/115016843