bzoj 1951 [SDOI2010]古代猪文 (欧拉定理+卢卡斯+CRT)

题目链接

G i n C n i G^{\sum_{i|n} C_{n}^{i}} m o d 999911659 mod999911659 意义下的值

如果 G P G、P 不互质,显然 G G P P 的倍数,答案为0

否则根据欧拉定理
G i n C n i G i n C n i m o d ϕ ( p ) G i n C n i m o d ( p 1 ) G^{\sum_{i|n} C_{n}^{i}} \equiv G^{\sum_{i|n} C_{n}^{i}mod\phi(p)} \equiv G^{\sum_{i|n} C_{n}^{i}mod(p-1)}

然后将 999911659 1 999911659-1 分解质因数

999911658 = 2 × 3 × 4679 × 35617 999911658=2\times3\times4679\times35617

然后根据卢卡斯定理,我们可以分别求出 C n i C_{n}^{i} 模这四个小质数的余数

于是我们得到了

  • C n i a 1 ( m o d 2 ) C_{n}^{i}\equiv a1(mod2)
  • C n i a 2 ( m o d 3 ) C_{n}^{i}\equiv a2(mod3)
  • C n i a 3 ( m o d 4679 ) C_{n}^{i}\equiv a3(mod4679)
  • C n i a 4 ( m o d 35617 ) C_{n}^{i}\equiv a4(mod35617)

这个东西显然可以用CRT合并
然后在随便写个快速幂就可以A掉此题了

代码如下:

#include<bits/stdc++.h>
#define mod 999911659
using namespace std;

long long p[]={0,2,3,4679,35617},lcm=999911658;
long long fac[5][50050],inv[5][50050];

long long kasumi(long long a,long long b,long long x)
{
	long long ans=1;
	while(b)
	{
		if(b&1) ans=ans*a%x;
		a=a*a%x;
		b>>=1;
	}
	return ans;
}

long long init(long long kd)
{
	fac[kd][0]=1;
	for(int i=1;i<p[kd];i++) fac[kd][i]=fac[kd][i-1]*i%p[kd];
	inv[kd][p[kd]-1]=kasumi(fac[kd][p[kd]-1],p[kd]-2,p[kd]);
	for(int i=p[kd]-2;i>=0;i--) inv[kd][i]=inv[kd][i+1]*(i+1)%p[kd];
}

long long c(long long n,long long m,long long kd)
{
	return fac[kd][m]*inv[kd][n]%p[kd]*inv[kd][m-n]%p[kd];
}

long long lucas(long long x,long long y,long long kd)
{
	if(x<p[kd]&&y<p[kd])
	{
		return c(x,y,kd);
	}
	return c(x%p[kd],y%p[kd],kd)*lucas(x/p[kd],y/p[kd],kd)%p[kd];
}

long long crt(long long x,long long y)
{
	long long x1=lucas(x,y,1);
	long long x2=lucas(x,y,2);
	long long x3=lucas(x,y,3);
	long long x4=lucas(x,y,4);
	long long a1=lcm/p[1];
	long long a2=lcm/p[2];
	long long a3=lcm/p[3];
	long long a4=lcm/p[4];
	long long b1=kasumi(a1,p[1]-2,p[1]);
	long long b2=kasumi(a2,p[2]-2,p[2]);
	long long b3=kasumi(a3,p[3]-2,p[3]);
	long long b4=kasumi(a4,p[4]-2,p[4]);
	return ((x1*a1%lcm*b1%lcm)+(x2*a2%lcm*b2%lcm)+(x3*a3%lcm*b3%lcm)+(x4*a4%lcm*b4%lcm)+lcm)%lcm;
}

long long gg(long long x)
{
	long long ans=0;
	for(int i=1;i*i<=x;i++)
	{
		if(x%i==0)
		{
			ans+=crt(i,x);
			ans%=lcm;
			if(x/i!=i)
			{
				ans+=crt(x/i,x);
				ans%=lcm;
			}
		}
	}
	return ans;
}

long long n,m;

int main()
{
	for(int i=1;i<=4;i++) init(i);
	scanf("%lld%lld",&n,&m);
	if(m%mod==0) return puts("0"),0;
	long long res=gg(n);
	printf("%lld\n",kasumi(m,res,mod));
}

猜你喜欢

转载自blog.csdn.net/qq_21829533/article/details/83150640