带余除法过不去样例求助代码有注释
查看原帖
带余除法过不去样例求助代码有注释
305854
Drind楼主2024/1/13 23:41

RT。

我跑出来 7 1 的逆是 855638017 305585006

和 8 0 6 2 9 1 相乘之后再倒过来只有两位是正确的。我从 FFT 板子的题解区里随机挑了一篇 NTT 题解,发现也是这个结果,网上找了个多项式乘法计算器也是这个结果,所以究竟是我的 NTT 写挂了还是我代码里其他地方有奇怪的问题呢?

代码只写了求商,求余数没写。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
const int g=3,gi=332748118;
const int p=998244353; 

int rev[N];

inline int qpow(int a,int index){
	int ans=1;
	while(index){
		if(index&1) ans=(ans*a)%p;
		a=(a*a)%p;
		index>>=1;
	}
	return ans;
}

inline void ntt(int a[],int len,int inv){
	for(int i=0;i<len;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
	for(int j=1;j<len;j<<=1){
		int wn=qpow(inv==1?g:gi,(p-1)/(j<<1));
		for(int k=0;k<len;k+=(j<<1)){
			int w0=1;
			for(int i=0;i<j;i++,w0=(w0*wn)%p){
				int tx=a[k+i],ty=w0*a[k+i+j]%p;
				a[k+i]=(tx+ty)%p; a[k+i+j]=((tx-ty)%p+p)%p;
			}
		}
	}
}

int ta[N],tb[N];
inline void mul(int a[],int b[],int len){//ntt板子求调
	memset(ta,0,sizeof ta); memset(tb,0,sizeof tb);
	for(int i=0;i<(len>>1);i++) ta[i]=a[i],tb[i]=b[i];
	ntt(ta,len,1); ntt(tb,len,1);
	for(int i=0;i<len;i++) ta[i]=(ta[i]*tb[i])%p;
	ntt(ta,len,-1); int inv=qpow(len,p-2);
	for(int i=0;i<len;i++) ta[i]=ta[i]*inv%p;
	for(int i=0;i<len;i++) a[i]=ta[i];
}

inline int add(int x,int y){//一个实现带模加法的函数
	x+=y; if(x>=p) x-=p; return x;
}

inline void init(int len,int L){//初始化rev数组用的
	for(int i=0;i<len;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
}

int tmp[2][N];

inline void inverse(int a[],int n){//求逆用的
	memset(tmp,0,sizeof tmp);
	int len=2,L=1,base=1,cur=0; init(len,L);
	tmp[cur][0]=qpow(a[0],p-2);
	while(base<=(n<<1)){//这边是倍增递推
		cur^=1;
		for(int i=0;i<len;i++) tmp[cur][i]=add(tmp[cur^1][i]*2,0);
		mul(tmp[cur^1],tmp[cur^1],len); mul(tmp[cur^1],a,len);
		for(int i=0;i<len;i++) tmp[cur][i]=add(tmp[cur][i],p-tmp[cur^1][i]);
		base<<=1; len<<=1; L++;
		if(base<=(n<<1)) init(len,L);
	}
	for(int i=0;i<=n;i++) a[i]=tmp[cur][i];
}

int a[N],b[N],invb[N],tmpa[N];

inline void fake_main(){
	int n,m; cin>>n>>m;
	for(int i=0;i<=n;i++) cin>>a[i];
	for(int i=0;i<=m;i++) cin>>b[i];
	for(int i=0;i<=n;i++) tmpa[i]=a[i];
	for(int i=0;i<=m;i++) invb[i]=b[i];
	reverse(tmpa,tmpa+n+1);//把F翻转 reverse(invb,invb+m+1);//把G翻转
	int len=1,L=0; while(len<=(n+m)*2) len<<=1,L++; 
	
	
	for(int i=0;i<len;i++) cout<<tmpa[i]<<" "; cout<<"\n";
	inverse(invb,m); //把翻转后的G求逆
	for(int i=0;i<len;i++) cout<<invb[i]<<" "; cout<<"\n";
	init(len,L); mul(tmpa,invb,len);//相乘
	reverse(tmpa,tmpa+n-m+1);//转回来
	for(int i=0;i<n-m+1;i++) cout<<tmpa[i]<<" "; cout<<"\n";//这里结果就不一样了。
}

signed main(){
	ios::sync_with_stdio(false);
	int t; t=1;
	while(t--) fake_main();
}

2024/1/13 23:41
加载中...