P2480 SDOI 古代猪文(自带其他详细基础数论)
P2480 SDOI2010古代猪文
题目大意:求
\(G^{\sum_{d|n}{n \choose d}}~mod~999911659\)
各种基础数论全家桶,做这个题相当于复习今天内容了
999911659为质数
费马小定理\(a^p\equiv a(mod~p)\),\(a^p~mod~p=a~mod~p\)
\(p是质数时,φ(p)=p-1,根据欧拉定理推论a^b\equiv a^{b~mod~φ(n)}=a^{b~mod~(p-1)}(mod~n)\)
化简可得\(a^{\sum d|nC_n^d~mod~999911658}mod999911659\)
质因数分解\(999911658 = 2*3*4679*35617\)
\(枚举每个d,再用个Lucas定理或其他鬼方法把C_n^d算出来,分别计算\sum C_n^d对四个质数取模结果记为a_1,a_3,a_3,a_4\)
跑个中国剩余定理
中国剩余定理:\(m_i是两两互质的整数,m=\prod_{i=1}^nm_i,M_i=m/m_i,t_i\)是线性同余方程\(M_it_i\equiv1(mod~m_i)\)
的一个解,对于任意的n个整数\(a_i\),方程组有整数解为\(x=\sum_{i=1}^na_iM_it_i\)
#include<cstdio>
#define maxn
#define mod 999911658
#define int long long
using namespace std;
int n,G,jc[40000],a[5],b[5]={0,2,3,4679,35617},ans;
inline int qpow(int a,int k,int p)
{
int res=1;
while(k)
{
if(k&1) res=(res*a)%p;
a=(a*a)%p;
k>>=1;
}
return res%p;
}
void jiecheng(int p){
jc[0] = 1;
for(int i = 1;i<=p;i++)
jc[i] = jc[i-1] * i % mod;
}
int C(int n,int m,int p){
if(n < m) return 0;
return jc[n] * qpow(jc[m],p-2,p) % p * qpow(jc[n-m],p-2,p) % p;
}
int lucas(int n,int m,int p){
if(n<m) return 0;if(!n) return 1;
return lucas(n/p,m/p,p)*C(n % p,m % p,p) % p;
}
void zgsy(){
for(int i=1;i<=4;i++)
ans=(ans+a[i]*(mod/b[i])%mod*qpow(mod/b[i],b[i]-2,b[i]))%mod;
}
signed main(){
scanf("%lld%lld",&n,&G);
if(G%(mod+1)==0){
printf("0\n");
return 0;
}//特判
for(int k=1;k<=4;k++){
jiecheng(b[k]);
for(int i=1;i*i<=n;i++){
if(n%i==0){
a[k]=(a[k]+lucas(n,i,b[k]))%b[k];
if(i*i!=n){
a[k]=(a[k]+lucas(n,n/i,b[k]))%b[k];
}
}
}
}//逐一枚举n的约数
zgsy();
printf("%lld\n",qpow(G,ans,mod+1));//注意mod要+1
return 0;
}
//一维递推组合数
cin>>n>>m;
m=min(m,n-m);
c[0]=1;
for (int i=1;i<=n;i++)
{
for (int j=m;j>=1;j--)
c[j]=c[j]+c[j-1];
}
cout<<c[m];
//线性推逆元
long long inv[10000005];
inv[1]=1;
long long ny(int x,int p)
{
if (inv[x] != 0) return inv[x];
inv[x]=(p - p / x) * ny(p % x,p) % p;
return inv[x];
}
//费马小定理求逆元 a mod p乘法逆元=a^(p-2)
快速幂`````
qpow(a,p-2)
//扩欧
void exgcd(LL a, LL b, LL &x, LL &y) //拓展欧几里得算法
{
if(!b) x = 1, y = 0;
else
{
exgcd(b, a % b, y, x);
y -= x * (a / b);
}
}
LL niYuan(LL a, LL b) //求a对b取模的逆元
{
LL x, y;
exgcd(a, b, x, y);
return (x + b) % b;
}
//曹冲养猪
#include<iostream>
#define ll long long
using namespace std;
int a[11],b[11],n;
ll mul = 1,t;
inline void Exgcd(ll a,ll b,ll &d,ll &x,ll &y){
if(!b){d=a;x=1;y=0;}
else{
Exgcd(b,a%b,d,x,y);
ll t=x;x=y;y=t-(a/b)*y;
}
}
int main(){
std::cin>>n;
ll ans=0,t,x,y,d;;
for(int i = 1;i <= n;i++){
std::cin>>a[i]>>b[i];
mul *= a[i];
}
for(int i = 1;i <= n;i++) {
t = mul / a[i];
Exgcd(t,a[i],d,x,y);
ans=((ans+t*x*b[i])%mul+mul)%mul;
}
std::cout<<(ans+mul) % mul;
}
计算器
BSGS,快速求出\(a^x\equiv b(mod~p)\)的最小非负整数解
将\(x\)拆分成\(i*m-j\)形式,\(m为sqrt(p)上取整,原式化成a^{i*m-j}\equiv b(mod~p)\)
\(a^{i*m}\equiv b*a^j(mod~p)\),从\(0-m\)枚举\(i\),算出所有的\(a^{i*m}\)
如果一个对应的\(a^{i*m}\)的值已经在哈希表,则表明\(i*m-j\)为一个解,输出此时的解
因为\(j\le m\),所以求出的解随\(i\)的增大而减小,所以最先求出\(i\)所对应的解,即为所求
、
、
、
、
、
、
\(a\equiv b(mod~n)\Leftrightarrow n|(a-b)\)
\(a\equiv b(mod~n),c\equiv d(mod~n)\Leftrightarrow a±c\equiv b±d(mod~n)\)
\(⇔ac\equiv bd(mod~n)⇔ka\equiv kb(mod~n)⇔a^m\equiv b^m\)
\(gcd(a,n)=1\)时\(ab\equiv ac(mod~n)⇔b\equiv c(mod~n)\)
\(φ(n)=\sum_{i=1}^n[gcd(i,n)=1][为布尔式],φ(1)=1,φ(p)=p-1,p\in prime\)
对于质数 p 的 k 次方 \(p^k\)显然:小于等于它的数一共 \(p^k\)个,只有含有质因数 p的数与它不互质,这些数为:
\(p,2p,3p⋯p^{k-1}⋅p\)共\(p-1\)个,\(故φ(p^k)=p∈Prime,k∈Z+\)
同时还能得到递推式:\(φ(p^{k+1})=p^{k+1}-p^k=p(p^k-p^{k-1})=p*φ(p^k)\)
欧拉函数筛法:
\(a^{p-1}\equiv1(mod~p)\)可得\(a^{n}\equiv a^{n~mod~(p-1)}(mod~p)\)
欧拉定理:\(gcd(a,m)=1可以得到a^{φ(m)}\equiv1(mod~m)\)
推论\(a^{n}\equiv(a~mod~m)^{(n~mod~φ(m))}(mod~m)\)