题解

前置技能

1.多项式求逆

求\(f(x)\*g(x) \equiv 1 \pmod {x^{t}}\)

我们在t == 1时,有\(f[0] = frac{1}{g[0]}\)

之后呢,我们倍增一下,假如新的答案是\(g'(x)\)在\(\pmod {x^{2t}}\)意义下,显然有

\(g'(x) - g(x) \equiv 0 \pmod {x^{t}}\)

我们两边平方一下

\(g'^{2}(x) - 2g'(x)g(x) + g^{2}(x) \equiv 0 \pmod {x^{2t}}\)

两边再乘上一个\(f(x)\)

\(g'(x) - 2g(x) + f(x)g^{2}(x) \equiv 0 \pmod {x^{2t}}\)

那么答案就是

\(g'(x) \equiv = g(x)(2 - f(x)g(x))\)

这是我们熟悉的卷积形式,可以直接上FFT

注意指数上界是e * 2因为有三个多项式相乘

2.多项式除法

\(f(x) = g(x)q(x) + r(x)\)

设\(f(x)\)的度数为\(n\),\(g(x)\)的度数为\(m\),\(q(x)\)的度数为\(n - m\)

\(r(x)\)的度数小于等于\(m - 1\)

\(f(\frac{1}{x}) = g(\frac{1}{x})q(\frac{1}{x}) + r(\frac{1}{x})\)

\(x^{n}f(\frac{1}{x}) = x^{n}g(\frac{1}{x})q(\frac{1}{x}) + x^{n}r(\frac{1}{x})\)

设\(R(f)\)为f的每项系数翻转过来

则式子可以变为

\(R(f) = R(g)R(q) + x^{n - m + 1}R(r)\)

再在两边取模\(x^{n - m + 1}\)

则\(R(q) \equiv \frac{R(f)}{R(g)} \pmod {x^{n - m + 1}}\)

3.多项式取模

做完多项式除法后,用减掉商和被除数的乘积

再来看这道题

我们发现,这个式子生成的方式有点难受,我们就把系数翻转过来

我们用指数大小代表是序列的第几项

然后呢,我们发现其实就是如果生成了一个\(x^{k + 1}\)我们要把它分解成那个线性递推式即\(\sum_{i = 1}^{k}a_{i}x^{i}\)

设\(g(x) = x^{k + 1} - \sum_{i = 1}^{k}a_{i}x^{i}\)

答案也就是\(x^{n} \pmod {g(x)}\)的结果

这样只要做多项式快速幂然后取模多项式就好了

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <vector>
#include <set>
//#define ivorysi
#define eps 1e-8
#define mo 974711
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define MAXN 30005
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
const int MOD = 25 * (1 << 22) + 1,G = 3,L = (1 << 22);
int W[L + 5],F[MAXN],K;
int64 N;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 - '0' + c;
c = getchar();
}
}
template<class T>
void out(T x) {
if(x < 0) putchar('-');
while(x >= 10) {
out(x / 10);
}
putchar(x % 10 + '0');
}
int fpow(int x,int c) {
int res = 1,t = x;
while(c) {
if(c & 1) res = 1LL * res * t % MOD;
t = 1LL * t * t % MOD;
c >>= 1;
}
return res;
}
struct poly {
int a[65537],deg;
poly() {
memset(a,0,sizeof(a));
deg = 0;
}
friend void NTT(poly &f,int on,int M) {
for(int i = 1 , j = M / 2 ; i < M - 1 ; ++i) {
if(i < j) swap(f.a[i],f.a[j]);
int k = M / 2;
while(j >= k) {
j -= k;
k >>= 1;
}
j += k;
}
for(int h = 2 ; h <= M ; h <<= 1) {
int wn = W[(L + on * L / h) % L];
for(int k = 0 ; k < M ; k += h) {
int w = 1;
for(int j = k ; j < k + h / 2 ; ++j) {
int u = f.a[j];
int t = 1LL * f.a[j + h / 2] * w % MOD;
f.a[j] = (u + t) % MOD;
f.a[j + h / 2] = (u + MOD - t) % MOD;
w = 1LL * wn * w % MOD;
}
}
}
if(on < 0) {
int Inv = fpow(M,MOD - 2);
for(int i = 0 ; i < M ; ++i) f.a[i] = 1LL * f.a[i] * Inv % MOD;
}
}
friend poly operator + (const poly &f,const poly &g) {
poly h;
int t = max(f.deg,g.deg);
for(int i = 0 ; i <= t ; ++i) {
h.a[i] = (f.a[i] + g.a[i]) % MOD;
}
for(int i = t ; i >= 0 ; --i) {
if(h.a[i] != 0) {h.deg = i;break;}
}
return h;
}
friend poly operator - (const poly &f,const poly &g) {
poly h;
int t = max(f.deg,g.deg);
for(int i = 0 ; i <= t ; ++i) {
h.a[i] = (f.a[i] + MOD - g.a[i]) % MOD;
}
for(int i = t ; i >= 0 ; --i) {
if(h.a[i] != 0) {h.deg = i;break;}
}
return h;
}
friend poly operator * (poly f,poly g) {
int M = 1;while(M <= f.deg + g.deg) M <<= 1;
NTT(f,1,M);NTT(g,1,M);
poly h;
for(int i = 0 ; i < M ; ++i) {
h.a[i] = 1LL * f.a[i] * g.a[i] % MOD;
}
NTT(h,-1,M);
for(int i = M - 1 ; i >= 0 ; --i) {
if(h.a[i] != 0) {
h.deg = i;
break;
}
}
return h;
}
friend void calc_Inverse(const poly &f,poly &g,int e) {
if(e == 1) {
g.a[0] = fpow(f.a[0],MOD - 2);
g.deg = 0;
return;
}
calc_Inverse(f,g,(e + 1) >> 1);
int M = 1;while(M <= g.deg * 2 + e - 1) M <<= 1;
poly t = f;t.deg = e - 1;
for(int i = e ; i < M ; ++i) t.a[i] = 0;
for(int i = g.deg + 1 ; i < M ; ++i) g.a[i] = 0;
NTT(g,1,M);NTT(t,1,M);
for(int i = 0 ; i < M ; ++i) {
g.a[i] = 1LL * g.a[i] * (2 + MOD - 1LL * g.a[i] * t.a[i] % MOD) % MOD;
}
NTT(g,-1,M);
for(int i = e ; i < M ; ++i) g.a[i] = 0;
g.deg = e - 1;
}
friend poly Inverse(const poly &f,int e) {
poly g;
calc_Inverse(f,g,e);
return g;
}
friend poly operator / (const poly &f,const poly &g) {
poly q;
if(f.deg < g.deg) return q;
poly Rf = f,Rg = g;
reverse(Rf.a,Rf.a + Rf.deg + 1);
reverse(Rg.a,Rg.a + Rg.deg + 1);
int t = f.deg - g.deg + 1;
for(int i = t ; i <= Rg.deg ; ++i) Rg.a[i] = 0;
for(int i = t ; i <= Rf.deg ; ++i) Rf.a[i] = 0;
Rf.deg = min(Rf.deg,t - 1);
Rg.deg = min(Rg.deg,t - 1);
poly Rq = Rf * Inverse(Rg,t);
q = Rq;
for(int i = t ; i <= q.deg ; ++i) q.a[i] = 0;
reverse(q.a,q.a + t);
q.deg = t - 1;
return q;
}
friend poly operator % (const poly &f,const poly &g) {
if(f.deg < g.deg) return f;
poly q = f / g;
return f - (g * q);
}
friend poly fpow(const poly &x,int64 c,const poly &Mod) {
poly res,t = x;
res.deg = 0;res.a[0] = 1;
while(c) {
if(c & 1) res = res * t % Mod;
t = t * t % Mod;
c >>= 1;
}
return res;
}
}M,X;
void Init() {
W[0] = 1,W[1] = fpow(G,25);
for(int i = 2 ; i < L ; ++i) W[i] = 1LL * W[i - 1] * W[1] % MOD;
read(K);read(N);
for(int i = 1 ; i <= K ; ++i) read(F[i]);
int a;
M.deg = K + 1;
for(int i = 1 ; i <= K ; ++i) {
read(a);
M.a[K - i + 1]= MOD - a;
}
M.a[K + 1] = 1;
X.deg = 1;X.a[1] = 1;
}
void Solve() {
X = fpow(X,N,M);
int64 ans = 0;
for(int i = 1 ; i <= K ; ++i) {
ans = ans + 1LL * X.a[i] * F[i] % MOD;
}
ans %= MOD;
printf("%lld\n",ans);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
return 0;
}

【Codechef】Random Number Generator(多项式除法)的更多相关文章

  1. 文献翻译|Design of True Random Number Generator Based on Multi-stage Feedback Ring Oscillator(基于多级反馈环形振荡器的真随机数发生器设计)

    基于多级反馈环形振荡器的真随机数发生器设计 摘要 真随机数生成器(trng)在加密系统中起着重要的作用.本文提出了一种在现场可编程门阵列(FPGA)上生成真随机数的新方法,该方法以 多级反馈环形振荡器 ...

  2. @codechef - RNG@ Random Number Generator

    目录 @description@ @solution@ @part - 1@ @part - 2@ @part - 3@ @accepted code@ @details@ @description@ ...

  3. Random Number Generator

    rand()函数可以产生[0,RAND_MAX]之间的均匀的伪随机数,它定义在头文件stdlib.h中,函数原型: int rand(void); C标准库的实现是: unsigned ; /*ran ...

  4. [spojRNG]Random Number Generator

    先将所有数加上Ri,即变为区间[0,2Ri],考虑容斥,将区间容斥为[0,+oo)-[2Ri,+oo),然后对[2Ri,+oo)令$bi=ai-2Ri$,相当于范围都是[0,+oo)问题转化为求n个正 ...

  5. Random number

    Original #include <stdlib.h> #include <time.h> srand(time(NULL)); rand(); The versions o ...

  6. Case Study: Random Number Generation(翻译教材)

    很荣幸,经过三天的努力.终于把自己翻译的教材做完了,现在把它贴出来,希望能指出其中的不足.   Case Study: Random Number Generation Fig. 6.7  C++ 标 ...

  7. ISO C Random Number Functions

    This section describes the random number functions that are part of the ISO C standard. To use these ...

  8. How to generate a random number in R

    Generate a random number between 5.0 and 7.5x1 <- runif(1, 5.0, 7.5) # 参数1表示产生一个随机数x2 <- runif ...

  9. Linux shell get random number

    the Shell Profile: When a new interactive shell is started, /etc/profile, followed by /etc/bash.bash ...

随机推荐

  1. Hadoop生态圈-使用MapReduce处理HBase数据

    Hadoop生态圈-使用MapReduce处理HBase数据 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.对HBase表中数据进行单词统计(TableInputFormat) ...

  2. The Difference Between Big Data and a Lot of Data

    The Difference Between Big Data and a Lot of Data The term “big data” has been around for a while no ...

  3. 简单理解 NP, P, NP-complete和NP-Hard

    P是一类可以通过确定性图灵机(以下简称 图灵机)在多项式时间(Polynomial time)内解决的问题集合. NP是一类可以通过非确定性图灵机( Non-deterministic Turing ...

  4. HDU 1256 画8 模拟题

    解题报告:这题我觉得题目有一个没有交代清楚的地方就是关于横线的字符的宽度的问题,题目并没有说,事实上题目要求的是在保证下面的圈高度不小于上面的圈的高度的情况下,横线的宽度就是等于下面的圈的高度. #i ...

  5. HDU 2079 选课时间 组合题

    解题报告:最多有8种学分的课,然后每种学分的课最多有10门,问要选学分为n的课一共有多少种选法,注意学分相同的课之间没有区别. 这题暴力可过,我用了8层循环,就简单了.听说可以用母函数,但没学过,看一 ...

  6. 用jsx语法写iview事件

    普通的vue事件,在jsx中写法为 on+方法名(首字母大写) . 如:onClick={....}.onChange={....}.onBlur={....} iview中的事件,在vue中默认是 ...

  7. C++ Primer 5th 第18章 用于大型程序的工具

    C++大规模程序设计至少存在三个特殊要求: 错误处理 库的引入 复杂建模 以上三种对应C++语言的三种特性:异常处理.命名空间.多重继承. 异常处理 异常处理机制是一种允许偷懒的工具,在出现非正确的情 ...

  8. Spring4笔记4--基于XML的DI(依赖注入)

    基于XML的DI(依赖注入): Bean 实例在调用无参构造器创建了空值对象后,就要对 Bean 对象的属性进行初始化.初始化是由容器自动完成的,称为注入.根据注入方式的不同,常用的有两类:设值注入. ...

  9. oracle建表,设置主键,修改属性等

    --建表 create table book( book_id number(10), book_name varchar2(20), book_price number(10,2), book_au ...

  10. gnome桌面无法使用笔记本的触摸板

    原来使用ubuntu的时候,升级了gnome之后触摸板就不能用了,不能说不能用了,应该是自己不会配置然后不好用了,具体状况如是,可以在登录界面gdm使用触摸板以及点击,但是进入桌面之后就不能点击了.后 ...