1. 程式人生 > >【FFT加速特徵多項式解線性遞推】hdu4914

【FFT加速特徵多項式解線性遞推】hdu4914

上一篇http://blog.csdn.net/huyuncong/article/details/18184873

雖然是FFT加速,但其實這道題限制挺強的,首先特徵多形式的次數雖然上萬,但是遞推式只涉及到2項,因此初項其實可以線性推出,而且模很小隻有119,因此FFT中不用取模,可以先算完再取模。

複雜度o(klogklogn)

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const double pi = acos(-1.0);
const int maxn = 1 << 18;
const int mo=119;
struct Complex {
    double x, y;

    Complex (double real = 0, double imag = 0) : x(real), y(imag) {}

    double &real() {
        return x;
    }

    double &imag() {
        return y;
    }
    
    void print()
    {
        cout<<"real="<<x<<" imag=%.7lf\n"<<y<<endl;
    }
}Pa[50000],Pb[50000],Pc[50000];
int f[50000];
int n,a,b,p,q,N;
Complex operator+(const Complex &a, const Complex &b) {
    return Complex(a.x + b.x, a.y + b.y);
}

Complex operator-(const Complex &a, const Complex &b) {
    return Complex(a.x - b.x, a.y - b.y);
}

Complex operator*(const Complex &a, const Complex &b) {
    return Complex(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
}

inline void sincos(double theta,double &p0,double &p1)
{
    p0=sin(theta);
    p1=cos(theta);
}

void FFT(Complex P[], int n, int oper)
{
    for (int i = 1, j = 0; i < n - 1; i++) {
        for (int s = n; j ^= s >>= 1, ~j & s;);
        if (i < j) {
            swap(P[i], P[j]);
        }
    }
    Complex unit_p0;
    for (int d = 0; (1 << d) < n; d++) {
        int m = 1 << d, m2 = m * 2;
        double p0 = pi / m * oper;
        sincos(p0, unit_p0.y, unit_p0.x);
        for (int i = 0; i < n; i += m2) {
            Complex unit = 1;
            for (int j = 0; j < m; j++) {
                Complex &P1 = P[i + j + m], &P2 = P[i + j];
                Complex t = unit * P1;
                P1 = P2 - t;
                P2 = P2 + t;
                unit = unit * unit_p0;
            }
        }
    }
}

struct poly{
	int u[50000];
	poly() {
		memset(u,0,sizeof(u));
	}
	poly operator *(poly &B) {
		poly c;
		for (int i=0;i<q;i++) Pa[i]=Complex(u[i],0);
		for (int i=0;i<N-q;i++) Pa[i+q]=Complex(0,0); 
		for (int i=0;i<q;i++) Pb[i]=Complex(B.u[i],0);
		for (int i=0;i<N-q;i++) Pb[i+q]=Complex(0,0);
		FFT(Pa,N,1),FFT(Pb,N,1);
		for (int i=0;i<N;i++) Pc[i]=Pa[i]*Pb[i];
		FFT(Pc,N,-1);
		for (int i=0;i<N;i++) c.u[i]=((long long)(Pc[i].x/N+0.5))%mo;
		for (int i=N;i>=q;i--)
			if (c.u[i])
				(c.u[i-p]+=(c.u[i]*a)%mo)%=mo,
				(c.u[i-q]+=(c.u[i]*b)%mo)%=mo;
		return c;
	}
	void print()
    {
        for (int i=0;i<q;i++) cout<<u[i]<<' ';cout<<endl;
    }
};
int func(int x)
{
	if (x<=0) return 1;
	return f[x];
}
void fgm(int e,poly &sum,poly &b)
{
	//poly b,sum;
	sum.u[0]=1;
	b.u[1]=1;
	for (;e;e>>=1) {
		if (e&1) sum=sum*b;
		b=b*b;
	}
}
int main()
{
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	for (;cin>>n>>a>>b>>p>>q;) {
		a%=mo,b%=mo;
		for (int i=1;i<=2*q;i++)
			f[i]=(a*func(i-p)+b*func(i-q))%mo;
		if (n<=2*q) {
			printf("%d\n",f[n]);			
			continue;
		}
		for (N=1;N<=q+q+1;N<<=1) ;		
		poly A,B;
		fgm(n-q,A,B);
		int ans=0;
		for (int i=q-1;i>=0;i--)
			ans=(ans+A.u[i]*f[i+q])%mo;
		printf("%d\n",ans);
/*		for (int i=1;i<=n;i++)
			f[i]=(a*func(i-p)+b*func(i-q))%mo;
		cout<<ans<<' '<<f[n]<<endl;
		if (ans!=f[n]) {
			freopen("ansput.txt","w",stdout);
			cout<<"NO"<<endl;
			return 0;
		}*/
	}
	//freopen("ansput.txt","w",stdout);
	//cout<<"YES"<<endl;
	return 0;
}


相關推薦

FFT加速特徵多項式線性hdu4914

上一篇http://blog.csdn.net/huyuncong/article/details/18184873 雖然是FFT加速,但其實這道題限制挺強的,首先特徵多形式的次數雖然上萬,但是遞推式只涉及到2項,因此初項其實可以線性推出,而且模很小隻有119,因此FFT中

焦作預選賽L題杜教線性 模板

真香,真好用,只許給出前幾項你就會體驗前所未有的快樂。 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #inclu

BZOJ4944NOI2017泳池 概率DP 常係數線性 特徵多項式 多項式取模

題目大意   有一個1001×n1001×n的的網格,每個格子有qq的概率是安全的,1−q1−q的概率是危險的。   定義一個矩形是合法的當且僅當: 這個矩形中每個格子都是安全的 必須緊貼網格的下邊界   問你最大的合法子矩形大小

bzoj4161: Shlw loves matrixI特徵多項式優化常係數齊次線性模板

Description 給定數列 {hn}前k項,其後每一項滿足 hn = a1*h(n-1) + a2*h(n-2) + … + ak*h(n-k) 其中 a1,a2…ak 為給定數列。請計算 h(n),並將結果對 1000000007 取模輸出。

XSY2730Ball 多項式exp 多項式ln 多項式開根 常係數線性 DP

題目大意   一行有n個球,現在將這些球分成k 組,每組可以有一個球或相鄰兩個球。一個球只能在至多一個組中(可以不在任何組中)。求對於1≤k≤m的所有k分別有多少種分組方法。   答案對998244353取模。   n≤109,m<219 題解

k階線性-特征多項式

true light scanf 特征 truct += return typedef zoj BZOJ4161 http://www.lydsy.com/JudgeOnline/problem.php?id=4161 #include<cstdio>

[學習筆記]多項式的整除、取模、多點求值和插值及常係數線性

一、開頭 ( WC2019 神犇協會) undefeatedKO : NOI2017 的題大家都 AK 了嗎? All : AK 了! ION :我們穿越到 2019 年的 WC 怎麼樣? olis :好啊!聽說一個弱雞 xyz32768 要來 WC ,我們一到就把他 D 一遍,這樣他

BM線性模板黑科技

#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <st

杜教BM模板 線性ACM-ICPC 2018 焦作賽區網路預賽 L. Poor God Water

 L. Poor God Water God Water likes to eat meat, fish and chocolate very much, but unfortunately, the doctor tells him that some sequence

BZOJ4161Shlw loves matrixI (常係數齊次線性

【BZOJ4161】Shlw loves matrixI (常係數齊次線性遞推) 題面 BZOJ 題解 \(k\)很小,可以直接暴力多項式乘法和取模。 然後就是常係數齊次線性遞推那套理論了,戳這裡 #include<iostream> #include<cstdio> #in

HDU 6172 and HDU 6185 線性 + 思維 + 板子

這兩道題都是給的線性遞推式(輸入只有一個未知數n), 那麼我寫這個部落格的目的就是儲存一個超強模板, 可以解決任何線性遞推式. 這個板子是我從百度之星複賽上”偷”的杜教的板子. 所以我們現在要做的是用絕對正確的方法求出遞推式的前幾項. 然後扔進這個板子就可以了.

多項式取模與線性優化

       最近51nod比賽最後一題,我列出母函式以後發現要求m<=10^16項係數,於是現在來寫一下這個問題。        假設f(x)=f(x)*g(x)+1。        經過詢問

多項式取模優化齊次線性

線性遞推 給出長為mm的數列a=⟨a1,a2,…,am⟩a=⟨a1,a2,…,am⟩,以及無窮數列ff的前mm項⟨f0,f1,…,fm−1⟩⟨f0,f1,…,fm−1⟩,對於∀i≥m∀i≥m,有fi=∑mj=1ajfi−jfi=∑j=1majfi−j。求fnf

BJ模擬 裝飾地板狀壓dp+特徵多項式優化矩陣快速冪

題目大意: 給一個m∗nm∗n的地板,有s1s1種1×21×2的橫地磚,s2s2種2×12×1的豎地磚,問有多少種鋪滿的方式,對998244353取模。 (m≤6,n≤102501,s1,s2≤1e9)(m≤6,n≤102501,s1,s2≤1e9)

關於迴問題的探討和優化,線性發散(未完待續,更新中)

遞迴介紹 首先來說一下遞迴,我們不講概念,我只說一下遞迴本身,有需要的同學請自行查閱資料。 遞迴分兩個階段,遞和歸 遞:是用來描

找規律二項式定理Codeforces Round #419 (Div. 1) B. Karen and Test

main turn logs pow 分享 string ren () 奇數 打個表出來看看,其實很明顯。 推薦打這倆組 11 1 10 100 1000 10000 100000 1000000 10000000 100000000 1000000000 10000000

LISGym - 101246H - ``North-East''

math put ast algo -i eas inpu freopen define x坐標排序,y坐標當權值,同一個x坐標的,y從大到小排。 求f(i)表示以i結尾的LIS以後,從後向前枚舉,不斷更新一個max數組,max(i)代表最長上升子序列為i時,當前的 結尾的

UVa 825簡單dp,

space 遞推 log 題目 logs .org str eof scan UVa 825 題意:給定一個網格圖(街道圖),其中有一些交叉路口點不能走。問從西北角走到東南角最短走法有多少種。(好像沒看到給數據範圍。、。) 簡單的遞推吧,當然也就是最簡單的動歸了。顯然最短路

線性式(外掛)

ons return main clear rep for near n-1 cond 傳入前幾項,輸出低n項的值 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath&g

bzoj4161 (k^2logn求線性式)

ret n) log span isp for hide -h close 分析:   我們可以寫把轉移矩陣A寫出來,然後求一下它的特征多項式,經過手動計算應該是這樣的p(x)=$x^k-\sum\limits_{i=1}^ka_i*x^{k-i}$   根據Cayle