何LOJ6183を見る(パーティションFFT)(生成関数)(特性方程式)を見ます

ポータル

まず、再帰的な特性方程式は、トピックを与えています リットル 2 - 2 λ 3 = 0 \ラムダ^ 2-2 * \ラムダ3 = 0 、2つの特徴的な根があります λ 1 = 3 , λ 2 = 1 \ Lambda_1 = 3、\ lambda_2 = -1

次いで、アイテムnは、次式のように表すことができます。 C 1 λ 1 n + C 2 λ 2 n C_1 * \ ^ N + lambda_1 C_2 * \ ^ n個lambda_2

それぞれ2つのプロセス上で、すべてのものを求めています λ a i \ラムダ^ {\和a_iを}

リクエスト生成機能が設定されています ( λ a i x + 1 ) \ PROD(\ラムダ^ {a_iを} X + 1) 、パーティション f f t FFT

弾性率が小さいため、精度が破裂べきではありません

#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int N = 1e5 + 5, Mod = 99991;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b;}
int mul(int a, int b){ return 1ll * a * b % Mod; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int ksm(int a, int b){ int ans = 1; for(;b;b>>=1,a=mul(a,a)) if(b&1) ans = mul(ans, a); return ans; }
cs int inv4 = ksm(4, Mod-2);
int n, k, a[N];
typedef long long ll;
typedef long double ld;
#define poly vector<int>
cs ld PI = acos(-1.0);
struct cp{
	ld x, y;
	cp(ld _x = 0, ld _y = 0){ x = _x, y = _y; }
	cp operator + (cs cp &a){ return cp(x+a.x, y+a.y);}
	cp operator - (cs cp &a){ return cp(x-a.x, y-a.y);}
	cp operator * (cs cp &a){ return cp(x*a.x - y*a.y, x*a.y + y*a.x); }
}A[N << 2], B[N << 2];
poly rev; int up, bit;
void init(int deg){
	bit = 0; up = 1; while(up < deg) up <<= 1, ++bit; rev.resize(up);
	for(int i = 0; i < up; i++) rev[i] = (rev[i>>1]>>1)|((i&1)<<(bit-1));
}
void FFT(cp *a, int typ){
	for(int i = 0; i < up; i++) if(i < rev[i]) swap(a[i], a[rev[i]]);
	for(int i = 1; i < up; i <<= 1){
		cp wn(cos(PI/i), sin(PI/i) * typ);
		for(int j = 0; j < up; j += (i<<1)){
			cp w(1, 0);
			for(int k = 0; k < i; k++, w = w * wn){
				cp x = a[k + j], y = a[k + j + i] * w;
				a[k + j] = x + y; a[k + j + i] = x - y;
			}
		}
	} 
}
poly operator * (poly a, poly b){
	int deg = a.size() + b.size() - 1; init(deg);
	for(int i = 0; i < a.size(); i++) A[i] = cp(a[i], 0);
	for(int i = a.size(); i < up; i++) A[i] = cp(0, 0);
	for(int i = 0; i < b.size(); i++) B[i] = cp(b[i], 0);
	for(int i = b.size(); i < up; i++) B[i] = cp(0, 0);
	FFT(A, 1); FFT(B, 1);
	for(int i = 0; i < up; i++) A[i] = A[i] * B[i];
	FFT(A, -1); a.resize(deg);
	for(int i = 0; i < deg; i++) a[i] = (ll)(A[i].x / up + 0.5) % Mod;
	return a;
}
poly Solve(int l, int r, int lambda){
	if(l == r){ poly f; f.push_back(1); f.push_back(ksm(lambda, a[l] % (Mod-1))); return f; }
	int mid = (l+r) >> 1; return Solve(l, mid, lambda) * Solve(mid+1, r, lambda);  
}
int main(){
	cin >> n >> k;
	for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
	int f0, f1; cin >> f0 >> f1;
	int C0 = mul(add(f0, f1), inv4), C1 = dec(f0, C0);
	cout << add(mul(C1, Solve(1, n, Mod-1)[k]), mul(C0, Solve(1, n, 3)[k]));
	return 0;
}
公開された610元の記事 ウォン称賛94 ビュー50000 +

おすすめ

転載: blog.csdn.net/sslz_fsy/article/details/103393901