为什么这能过啊?
查看原帖
为什么这能过啊?
939957
wanjiabao楼主2025/7/21 19:54

这是我的C函数:

int C(int n,int m,int p,int pr){
	if(n<m)return 0;
	long long f1=fac(n,p,pr),f2=fac(m,p,pr),f3=fac(n-m,p,pr),vt=0;
	for(int i=p;i<=n;i*=p)vt+=n/i;
	for(int i=p;i<=m;i*=p)vt-=m/i;
	for(int i=p;i<=n-m;i*=p)vt-=(n-m)/i;
	return ksm(p,vt,pr)*f1%pr*ksm(f2,pr-pr/p-1,pr)%pr*ksm(f3,pr-pr/p-1,pr)%pr;
}

可以看到我求fac函数的逆元时是用的ksm(f2,pr-pr/p-1,pr),但正常不应该是用扩欧求吗。当时自己抄的一个神秘代码直接过了,不过用ksm(f2,pr-2,pr)是正常的WA 80pts。

如果ksm(f2,pr-pr/p-1,pr)真是f2的逆元,那么fprpr11f1f^{p^r-p^{r-1}-1}f\equiv 1,也就是fprpr11f^{p^r-p^{r-1}}\equiv 1,什么鬼啊……

附源代码:

#include<bits/stdc++.h>
#define int  long long
using namespace std;
int exgcd(int a,int b,int &x,int &y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	int nx,ny;
	int g=exgcd(b,a%b,nx,ny);
	x=ny;
	y=nx-a/b*ny;
	return g;
}
int ksm(int a,int p,int m){
	if(p==0)return 1;
	long long tmp=ksm(a,p/2,m);
	if(p&1)return tmp*tmp%m*a%m;
	else return tmp*tmp%m;
}
int fac(int v,int p,int pr){
	if(!v)return 1;
	long long res=1;
	for(int i=1;i<=pr;i++){
		if(i%p)res=res*i%pr;
	}
	res=ksm(res,v/pr,pr);
	for(int i=1;i<=v%pr;i++){
		if(i%p)res=res*i%pr;
	}
	return res*fac(v/p,p,pr)%pr;
}
int C(int n,int m,int p,int pr){
	if(n<m)return 0;
	long long f1=fac(n,p,pr),f2=fac(m,p,pr),f3=fac(n-m,p,pr),vt=0;
	for(int i=p;i<=n;i*=p)vt+=n/i;
	for(int i=p;i<=m;i*=p)vt-=m/i;
	for(int i=p;i<=n-m;i*=p)vt-=(n-m)/i;
	return ksm(p,vt,pr)*f1%pr*ksm(f2,pr-pr/p-1,pr)%pr*ksm(f3,pr-pr/p-1,pr)%pr;
}
int exFocalors(int n,int m,int mod){
	int v=mod;
	vector<int>r,a;
	for(int i=2;i*i<=v;i++){
		if(v%i==0){
			int nr=1;
			while(v%i==0){
				v/=i;
				nr*=i;
			}
			int na=C(n,m,i,nr);
			r.push_back(nr);
			a.push_back(na);
		}
	}
	if(v>1){
		int nr=v,na=C(n,m,v,v);
		r.push_back(nr);
		a.push_back(na);
	}
	v=mod;
	int ans=0;
	for(int i=0,x,y;i<r.size();i++){
		int g=exgcd(v/r[i],r[i],x,y);
		x=(x%r[i]+r[i])%r[i];
		ans=(ans+v/r[i]*a[i]*x%v)%v;
	}
	return ans;
}
int p,n,m,ans=1;
signed main(){
	cin>>n>>m>>p;
	cout<<exFocalors(n,m,p)<<endl;
}
2025/7/21 19:54
加载中...