2019牛客暑期多校训练营(第三场)D题Big Integer

很好的题解思路博客
代码思路和上面博客一样

#include
using namespace std;
typedef long long ll;
ll n,m,p,a[105],b[105],r,cnt;

ll cal(ll x){//分解x得到分解后的因子a和指数b 
	cnt=0;
	int j=2;
	while(j*j<=x){ 
		if(x%j==0){
			cnt++;
			a[cnt]=j,b[cnt]=0;
			while(x%j==0)b[cnt]++,x/=j;
		}
		j++;
	}
	if(x>1){
		cnt++;
		a[cnt]=x,b[cnt]=1;
	}
} 

ll fp(ll x,ll y,ll mod){
	ll ret=1;
	while(y){
		if(y&1)ret=ret*x%mod;
		x=x*x%mod;
		y/=2;
	}
	return ret;
} 

ll solve(ll n,ll m,ll x){//求有多少对i,j满足10^(i^j)%p==1
	ll mx=0,ans=0;
	cal(x);
	for(int i=1;i<=cnt;i++)mx=max(mx,b[i]);//唯一分解中最大的指数 
	for(int i=1;i<=min(mx,m);i++){
		ll ret=1;
		for(int j=1;j<=cnt;j++){
			int s=(b[j]+i-1)/i;
			for(int k=0;k<s;k++)ret=ret*a[j];
		}
		ans+=n/ret;
	} 
	if(m>mx){
		ll ret=1;
		for(int i=1;i<=cnt;i++)ret=ret*a[i];	
		ans+=(m-mx)*(n/ret);
	}
	return ans;
}


int main(){
	int T;
	cin>>T;
	while(T--){
		cin>>p>>n>>m;
		if(p==2||p==5){
			puts("0");
			continue;
		}				
		if(p==3)r=3;//如果p==3要特判 
		else {
			r=p-1;//r为循环节 
			cal(r);
			for(int i=1;i<=cnt;i++)//看是否能在r的因子中找到更小的循环节 
				for(int j=0;j<b[i];j++)if(fp(10%p,r/a[i],p)==1)r/=a[i]; 
		}
		cout<<solve(n,m,r)<<endl; 
	}
}

你可能感兴趣的:(数论)