【常系数线性递推】51nod1538 一道难题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34454069/article/details/88879994

分析:

懒得去卡常。。。
一个比较有效的卡常方式是:维护最高系数非零项,每次做乘法&取模的时候,以那一项为多项式长度。
坑先留着。。以后来补

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define SF scanf
#define PF printf
#define MOD 104857601
#define MAXN 200010
using namespace std;
typedef long long ll;
int a[MAXN];
ll m,f[MAXN],g[MAXN],t[MAXN],rs[MAXN];
const int G=3;
ll fsp(ll x,int y){
	ll res=1;
	while(y){
		if(y&1)
			res=res*x%MOD;
		x=x*x%MOD;
		y>>=1;
	}
	return res;
}
void NTT(ll A[],int N,int flag){
	for(int i=1,j=0;i<N;i++){
		for(int d=N;j^=d>>=1,~j&d;);
		if(i<j)
			swap(A[i],A[j]);	
	}
	for(int i=1;i<N;i<<=1){
		ll wn=fsp(G,(MOD-1)/(i<<1));
		if(flag)
			wn=fsp(wn,MOD-2);
		for(int j=0;j<N;j+=(i<<1)){
			ll w=1;
			for(int k=0;k<i;k++,w=w*wn%MOD){
				ll x=A[j+k],y=A[i+j+k]*w%MOD;
				A[j+k]=(x+y)%MOD;
				A[i+j+k]=(x-y+MOD)%MOD;	
			}
		}
	}
	if(flag){
		ll invN=fsp(N,MOD-2);
		for(int i=0;i<N;i++)
			A[i]=A[i]*invN%MOD;	
	}
}
void inv(ll A[],ll B[],int N){
	if(N==1){
		B[0]=fsp(A[0],MOD-2);
		return ;
	}
	inv(A,B,(N+1)>>1);
	static ll tmp1[MAXN];
	for(int i=0;i<N;i++)
		tmp1[i]=A[i];
	int p=1;
	while(p<=N*2)
		p<<=1;
	NTT(tmp1,p,0);
	NTT(B,p,0);
	for(int i=0;i<p;i++)
		B[i]=B[i]*(2ll-tmp1[i]*B[i]%MOD+MOD)%MOD;
	NTT(B,p,1);
	for(int i=N;i<p;i++)
		B[i]=0;
	for(int i=0;i<p;i++)
		tmp1[i]=0;
}
void mul(ll A[],ll B[],int N,int M,ll res[]){
	static ll tmp1[MAXN],tmp2[MAXN];
	for(int i=0;i<N;i++)
		tmp1[i]=A[i];
	for(int i=0;i<M;i++)
		tmp2[i]=B[i];
	int p=1;
	while(p<=N+M)
		p<<=1;
	NTT(tmp1,p,0);
	NTT(tmp2,p,0);
	for(int i=0;i<p;i++)
		res[i]=tmp1[i]*tmp2[i]%MOD;
	NTT(res,p,1);
	for(int i=0;i<p;i++)
		tmp1[i]=tmp2[i]=0;
}
//void PolyMod(ll A[],ll B[],int N,int M){
//	static ll tmp1[MAXN],tmp2[MAXN],tmp3[MAXN];
//	for(int i=0;i<N;i++)
//		tmp1[i]=A[N-i-1];
//	for(int i=0;i<M;i++)
//		tmp2[i]=B[M-i-1];
//	inv(tmp2,tmp3,M);
//	mul(tmp1,tmp3,N,N-M+1,tmp3);
//	reverse(tmp3,tmp3+N-M+1);
//	mul(tmp2,tmp3,M,N-M+1,tmp1);
//	for(int i=0;i<M-1;i++)
//		A[i]=(A[i]-tmp1[i]+MOD)%MOD;
//	for(int i=0;i<4*(N+1);i++)
//		tmp1[i]=tmp2[i]=tmp3[i]=0;
//}
void PolyMod(ll A[],ll B[],int N,int M){
    static ll ta[MAXN],tb[MAXN],tmp[MAXN];
    for(int i=0;i<N;i++) ta[i]=A[N-i-1];
    for(int i=0;i<M;i++) tb[i]=B[M-i-1];
    inv(tb,tmp,M);
    for(int i=0;i<N-M+1;i++) tb[i]=tmp[i];
    for(int i=0;i<4*M;i++) tmp[i]=0;
    mul(ta,tb,N,N-M+1,tmp);
    reverse(tmp,tmp+N-M+1);
    mul(B,tmp,M,N-M+1,tmp);
    for(int i=0;i<M-1;i++)
        A[i]=(A[i]-tmp[i]+MOD)%MOD;
    for(int i=0;i<4*(N+1);i++)
        tmp[i]=0;
}
void mul(ll A[],ll B[],ll Mod[],ll res[]){
	int N=23333;
	mul(A,B,N,N,res);
	PolyMod(res,Mod,2*N,N+1);
}
int main(){
	int n,A,B;
	int N=23333;
	SF("%d%lld",&n,&m);
	SF("%d%d%d",&a[1],&A,&B);
	for(int i=2;i<=n;i++)
		a[i]=(a[i-1]*A+B)%N+1;
	for(int i=1;i<=n;i++)
		g[a[i]]=(g[a[i]]+MOD-1)%MOD;
	g[0]++;
//	for(int i=1;i<=n;i++)
//		PF("%lld ",a[i]);
//	PF("\n");
	inv(g,t,N);
	memset(g,0,sizeof g);
	for(int i=1;i<=n;i++)
		f[N-a[i]]=(f[N-a[i]]+MOD-1)%MOD;
	f[N]++;
	rs[0]=1;
	g[1]=1;
	while(m){
		if(m&1ll)
			mul(rs,g,f,rs);
		mul(g,g,f,g);
		m>>=1ll;
	}
	ll ans=0;
	for(int i=0;i<N;i++)
		ans=(ans+t[i]*rs[i]%MOD)%MOD;
	PF("%lld",ans);
}

猜你喜欢

转载自blog.csdn.net/qq_34454069/article/details/88879994
今日推荐