D. El número de pares (pensamiento + teoría de números + tamiz de Euler / A Si Si)

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


Solución de referencia:

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


Ideas:

Primero, se pueden obtener las condiciones suficientes y necesarias para la solución del teorema de Pei Shu ax + by = c 

Para la ecuación mcm (a, b) * c + mcd (a, b) * (- d) = x, x debe ser un múltiplo de mcd (mcd (a, b), lcm (a, b))

Considere mcd (a, b) como el factor primo de a, by tome min, y lcm (a, b) como el factor primo de a, by tome max, puede encontrar que la respuesta sigue siendo mcd (a, B)

Por lo tanto, se puede saber que mcd (a, b) es un divisor de x. En este momento, sqrt puede enumerar el valor de mcd (a, b). Como se conoce c, d, O1 puede obtener lcm (a , b);

En este punto, el problema es cuántos pares de abs que satisfacen mcd (a, b) y mcm (a, b) ya se conocen.

Aquí está la parte de la conclusión y la parte del pensamiento comparativo.

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

 


En este punto, se puede usar 2 ^ nO1 para calcular la respuesta, pero debe tenerse en cuenta que debe satisfacerse la divisibilidad de la fórmula. Es decir, lcm% c == 0 y lcm debe ser un múltiplo de gcd.

 

Así que empieza la parte de preprocesamiento. Normalmente, terminamos el registro ejecutado por Euler Sieve, n + nlogn. Sin embargo, abrí LL, lo que provocó que tle1 se confundiera durante mucho tiempo. Finalmente, 1996ms se estancó.

#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;
}

 


Esto es demasiado peligroso. Al ver que todos los demás son Essie, ¿no está Euler trabajando? Todavía se puede filtrar en

Veamos de nuevo a Euler Sieve, num [i] es el número de factores primos de i. Cuando i% primes [j]! = 0, la actualización de num [i * primes [j]] proviene de una parte de num [i] y primes [j].

Cuando i% primes [j [== 0, los primes [j] están contenidos en num [i]. Por lo tanto num [i * primes [j] = num [i]

Luego, On corrió. 1200ms.

Todavía no es rápido. ¿Son 1005ms para tamizar la 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;
}

 

Supongo que te gusta

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/115016843
Recomendado
Clasificación