洛谷P4723 模板 線性遞推

2022-05-23 21:24:09 字數 3119 閱讀 7509

題目大意:求乙個滿足$k$階齊次線性遞推數列$a_i$的第$n$項。

即:$a_n=\sum\limits_^f_i \times a_$

解:線性齊次遞推,先見洛谷題解,下回再補

卡點:陣列大小計算錯誤,求逆中途計算時忘記加$mod$等

c++ code:(這份全部是板子,可以用來測試,但是常數巨大)

#include #include #include #include #include #define maxk 32010

#define maxn 131072

const int mod = 998244353;

#define mul(x, y) static_cast(x) * (y) % mod

namespace math

inline int inv(int x)

}inline void reduce(int &x)

namespace poly

inline void fft(int *a, const int op = 1)

} if (!op)

} void inv(int *a, int *b, int n)

static int c[n], d[n];

const int len = n + 1 >> 1;

inv(a, b, len), init(len * 3);

std::memcpy(c, a, n << 2), std::memset(c + n, 0, lim - n << 2);

std::memcpy(d, b, len << 2), std::memset(d + len, 0, lim - len << 2);

fft(c), fft(d);

for (int i = 0; i < lim; ++i) d[i] = (2 - mul(d[i], c[i]) + mod) * d[i] % mod;

fft(d, 0);

std::memcpy(b + len, d + len, n - len << 2);

} void div(int *a, int *b, int *q, int n, int m)

void div_mod(int *a, int *b, int *q, int *r, int n, int m)

void mod(int *a, int *b, int m)

void pow(int *base, int p, int *mod, int m)

p >>= 1;

if (p)

} std::memcpy(base, res, m << 2);

} int solve(int *f, int *a, int n, int k)

#undef n

}int n, k;

int f[maxk], a[maxk];

int main()

std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);

std::cin >> n >> k;

for (int i = 1; i <= k; ++i) std::cin >> f[i];

for (int i = 0; i < k; ++i) std::cin >> a[i], reduce(a[i]);

std::cout << poly::solve(f, a, n, k) << '\n';

return 0;

}

發現取模的那乙個多項式是一定的,可以預處理出它的逆元以及點值表示式等,減小常數。

c++ code:(這乙份常數還算正常)

#include #include #include #include #include #define maxk 32010

#define maxn 65536

const int mod = 998244353;

#define mul(x, y) static_cast(x) * (y) % mod

namespace math

inline int inv(int x)

}inline void reduce(int &x)

namespace poly

inline void fft(int *a, const int op = 1)

} if (!op)

} void inv(int *a, int *b, int n)

static int c[n], d[n];

const int len = n + 1 >> 1;

inv(a, b, len), init(len * 3);

std::memcpy(c, a, n << 2), std::memset(c + n, 0, lim - n << 2);

std::memcpy(d, b, len << 2), std::memset(d + len, 0, lim - len << 2);

fft(c), fft(d);

for (int i = 0; i < lim; ++i) d[i] = (2 - mul(d[i], c[i]) + mod) * d[i] % mod;

fft(d, 0);

std::memcpy(b + len, d + len, n - len << 2);

} int g[n], invg[n];

void div(int *a, int *q, int n, int m)

void div_mod(int *a, int *r, int n, int m)

void pow(int *a, int p, int m)

div_mod(t, a, 2 * m, m + 1);

} int solve(int *f, int *a, int n, int k)

#undef n

}int n, k;

int f[maxk], a[maxk];

int main()

洛谷P4723 模板 線性遞推(多項式取模)

傳送門 考慮說要求乙個 a n i 1 kan if ia n sum a f i an i 1k an i fi 寫成矩陣的形式就是 a n an 1 f a0 fn a n a f a 0f n an an 1 f a0 fn實際上f nf n fn最後就是乙個長度為k kk的向量 滿足a n ...

洛谷 P3811 模板 乘法逆元 線性遞推逆元

給出n,p,求1 n所有數模p意義下的逆元.無論是擴充套件歐幾里得還是費馬小定理都是o n log 的,會t,這題因為是求1 n的所有數的逆元,因而可以遞推,若要求inv i 則可以設k p i,b p i.那麼k i b p 則k i b與0同餘.所以k i與 b同餘.所以k inv b 與 in...

洛谷 P3812 模板 線性基

這是一道模板題。給定n個整數 數字可能重複 求在這些數中選取任意個,使得他們的異或和最大。第一行乙個數n,表示元素個數 接下來一行n個數 僅一行,表示答案。輸入 1 2 1 1輸出 1 11 n 50,0 si 250 1 leq n leq 50,0 leq s i leq 2 1 n 50,0 ...