卧薪尝胆,厚积薄发。
      
    
            DZY Loves Math III
        
        
        Description:
求
$xy\equiv q\mod p$
的整数解
$(x,y)$
的数量,其中
$0\leqslant x,y<p$
。
$1\leqslant n\leqslant10,P,Q\leqslant (10^{18})^n$
Solution:
首先方程可以化为
$xy+pk=q$
,这个方程在当
$\gcd(x,p)|q$
时有
$\gcd(x,p)$
个解,这个可以推出通解形式然后就很显然了,那么实际上让求得就是:
$$
\begin{align}
&\sum_{d|p,d|q}d\sum_{x=0}^{p-1}[\gcd(x,p)=d]\\
=&\sum_{d|p,d|q}d\sum_{x=1}^{\frac p d}[\gcd(x,\frac p d)=1]\\
=&\sum_{d|p,d|q}d\varphi(\frac p d)
\end{align}
$$
然后有一个很重要的技巧就是把质因子的贡献分开考虑,因为函数积性,于是有:
$$
\begin{align}
&\sum_{d|p,d|q}\prod p_i^{k_{d_i}}\varphi(p_i^{k_{p_i}-k_{d_i}})\\
=&\prod_{i=1}^s\sum_{d|p,d|q} p_i^{k_{d_i}}\varphi(p_i^{k_{p_i}-k_{d_i}})\\
=&\prod_{i=1}^s\sum_{d|p,d|q} p_i^{k_{d_i}}p_i^{k_{p_i}-k_{d_i}-1}(p_i-1)\\
=&\prod_{i=1}^s\sum_{d|p,d|q} p_i^{k_{p_i}-1}(p_i-1)\\
=&\prod_{i=1}^sp_i^{k_{p_i}-1}(p_i-1)(k_{p_i}+1)\\
\end{align}
$$
但是这样不太对,因为当
$k_{d_i}=k_{p_i}$
时,
$\frac p d=1$
,此时
$\varphi(1)=1$
,也就是说如果
$\gcd(p,q)$
中
$p_i$
的指数和
$p$
相同,那么就应该加一。
与使用
$pollard-rho$
分解质因数判断即可。
当
$q=0$
时要特判,题解直接把
$q$
设成
$p$
感觉很妙。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
typedef long long ll;
int n;
#define MAXN 12
ll p[MAXN],q[MAXN];
ll fac[700];
ll mul(ll a,ll b,ll p)
{
	a %= p;b %= p;
	return ((a * b - (ll)(((long double)a * b + 0.5) / p) * p) % p + p) % p;
}
ll power(ll a,ll b,ll p)
{
	ll res = 1;
	while(b > 0)
	{
		if(b & 1)res = mul(res,a,p);
		a = mul(a,a,p);
		b = b >> 1;
	}
	return res;
}
bool check(ll a,ll b,ll n)
{
	if(b & 1)return true;
	ll t = power(a,b >> 1,n);
	if(t == 1)return check(a,b >> 1,n);
	else if(t == n - 1)return true;
	else return false;
}
ll prime[12] = {2,3,5,7,11,13,17,19,23,29,31,37};
bool test(ll n)
{
	if(n == 1)return true;
	for(int i = 0;i < 12;++i)
	{
		if(n == prime[i])return true;
		else if(power(prime[i],n - 1,n) != 1)return false;
		else if(!check(prime[i],n - 1,n))return false;
	}
	return true;
}
ll gcd(ll a,ll b){return (b == 0 ? a : gcd(b,a % b));}
ll rho(ll n,ll c)
{
	ll x = rand() % n,y = x,t = 1;
	for(int i = 1,k = 2;t == 1;++i)
	{
		x = (mul(x,x,n) + c) % n;
		t = gcd(abs(x - y),n);
		if(i == k)y = x,k = k << 1;
	}
	return t;
}
void solve(ll n)
{
	if(n == 1)return;
	if(test(n)){fac[++fac[0]] = n;return;}
	ll t = n;
	while(t == n)
	{
		t = rho(n,rand() % 5 + 1);
	}
	solve(t);solve(n / t);
	return;
}
#define MOD 1000000007
ll cntp[700],cntq[700];
int main()
{
	scanf("%d",&n);
	for(int i = 1;i <= n;++i)scanf("%lld",&p[i]);
	for(int i = 1;i <= n;++i)scanf("%lld",&q[i]);
	bool tag = false;
	ll ans = 1;
	for(int i = 1;i <= n;++i)solve(p[i]);
	sort(fac + 1,fac + 1 + fac[0]);
	fac[0] = unique(fac + 1,fac + 1 + fac[0]) - fac - 1;
	for(int i = 1;i <= n;++i)
	{
		for(int k = 1;k <= fac[0];++k)
		{
			ll v = p[i];
			while(v % fac[k] == 0)
			{
				++cntp[k];
				v /= fac[k];
			}
		}
	}
	for(int i = 1;i <= n;++i)
	{
		if(q[i] == 0)
		{
			for(int k = 1;k <= fac[0];++k)cntq[k] = cntp[k];
			tag = true;
			break;
		}
	}
	if(!tag)
	{ 
		for(int i = 1;i <= n;++i)
		{
			for(int k = 1;k <= fac[0];++k)
			{
				ll v = q[i];
				while(v % fac[k] == 0)
				{
					++cntq[k];
					v /= fac[k];
				}
			}
		}
	}
	for(int i = 1;i <= fac[0];++i)
	{
		cntq[i] = min(cntq[i],cntp[i]);
		ans = ans * power(fac[i],cntp[i] - 1,MOD) % MOD * ((fac[i] - 1) % MOD * (cntq[i] + 1) % MOD + (cntp[i] == cntq[i])) % MOD;
	}
	cout << ans << endl;	
	return 0;
} 
        Copyright © 2020
        
          wjh15101051
        
      
      ღゝ◡╹)ノ♡
     Date: Tue Dec 11 18:57:53 CST 2018
          Date: Tue Dec 11 18:57:53 CST 2018
           In Category:
          In Category:
           In tag:
          In tag:
 
         Timeline
            Timeline
           About
            About
           Toolbox
            Toolbox
           Friends
              Friends