某考试 T1 table

    我们把每一行看成一个多项式 f[i][1] + f[i][2] * x + f[i][3] * x^2 + ..... + f[i][n] * x^(n-1) 的话,一行转移到下一行就相当于乘上一个{b*x + a}的多项式。

    于是本题就有了不下五种做法233333,但是大部分做法都因为用了多次NTT而被卡常,就算只用了一次NTT的算法过了,那也不是最优的,因为我们完全可以把 (b*x + a)^n 广义二项式展开,这样就可以 O(N) 计算出转移多项式 (因为n<0也适用广义多项式定理,所以多项式求逆干嘛)。

    而且因为询问只问一个点的值,所以我们直接暴力卷积算出这个点的值就行了,根本不用写NTT把这一行都算出来(别拦我我要去跳楼)。然后考场我就是因为把这一行都算出来了...导致复杂度在O(NK)上多了一个log

好不容易想到广义二项式展开了最后还是只有40分qwq。。。。。

/*
    (bx + a)^n 广义二项式定理展开 
    
    (bx)^k * a^(n-k) * n^k_ * (1/k!)
    
	 x=0 : a^n * n^0_ * (1/0!)
	 x=1 : (bx)^1 * a^(n-1) * n^1_ * (1/1!)
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<cstring>
#define ll long long
using namespace std;
const int maxn=100000;
const int ha=998244353;
int o[maxn+5],ni[maxn+5];
int n,m,A,B,P,Q,jc[maxn+5];

inline int add(int x,int y){
	x+=y;
	return x>=ha?x-ha:x;	
}

inline int ksm(int x,int y){
	int an=1;
	for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;
	return an;
}

inline void init(){
	jc[0]=1;
	for(int i=1;i<=maxn;i++) jc[i]=jc[i-1]*(ll)i%ha;
	ni[maxn]=ksm(jc[maxn],ha-2);
	for(int i=maxn;i;i--) ni[i-1]=ni[i]*(ll)i%ha;
}

inline int get(int x,int y){
	if(!x) return o[y];
	int C=(x>0?ksm(A,x):ksm(ksm(A,-x),ha-2)),invA=ksm(A,ha-2);
	int ans=0,S=1,now=add(x,ha);
	
	for(int i=0;i<=y;S=S*(ll)now%ha,now=add(now,ha-1),i++){
		ans=add(ans,S*(ll)ni[i]%ha*(ll)C%ha*(ll)o[y-i]%ha);
		C=C*(ll)B%ha*(ll)invA%ha;
	}
	
	return ans;
}

inline void solve(){
	for(int i=0;i<n;i++) scanf("%d",o+i);
	while(Q--){
		int row,line;
		scanf("%d%d",&row,&line),line--;
		printf("%d
",get(row-P,line));
	}
}

int main(){
//	freopen("table.in","r",stdin);
//	freopen("table.out","w",stdout);
	init();
	scanf("%d%d%d%d%d%d",&m,&n,&A,&B,&P,&Q);
	solve();
	return 0;
}

  

原文地址:https://www.cnblogs.com/JYYHH/p/8676067.html