Others

Others

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//求最小的i,使得a[i] = key,若不存在,则返回-1
int Equal_Min(int a[], int n, int key) {
int m, l = 0, r = n - 1; //闭区间[0, n - 1]
while (l < r) {
m = l + ((r - l) >> 1);
if (a[m] >= key)r = m - 1;
else l = m + 1;
}
return (m < n) && (a[m] == key) ? m : -1;
}
//求最大的i,使得a[i] = key,若不存在,则返回-1
int Equal_Max(int a[], int n, int key) {
int m, l = 0, r = n - 1; //闭区间[0, n - 1]
while (l < r) {
m = l + ((r - l) >> 1);
if (a[m] > key)r = m - 1;
else l = m + 1;
}
return (l - 1 >= 0 && (a[l - 1] == key)) ? l - 1 : -1;
}
//求最小的i,使得a[i] > key,若不存在,则返回-1
int Grater(int a[], int n, int key) {
int m, l = 0, r = n - 1; //闭区间[0, n - 1]
while (l <= r) {
m = l + ((r - l) >> 1);
if (a[m] > key) r = m - 1;
else l = m + 1;
}
return l < n ? l : -1;
}
//求最小的i,使得a[i] >= key,若不存在,则返回-1
int Grater_Equal(int a[], int n, int key) {
int m, l = 0, r = n - 1; //闭区间[0, n - 1]
while (l <= r) {
m = l + ((r - l) >> 1);
if (a[m] >= key) r = m - 1;
else l = m + 1;
}
return l < n ? l : -1;
}
//求最大的i,使得a[i] < key,若不存在,则返回-1
int Smaller(int a[], int n, int key) {
int m, l = 0, r = n - 1; //闭区间[0, n - 1]
while (l <= r) {
m = l + ((r - l) >> 1);
if (a[m] >= key) r = m - 1;
else l = m + 1;
}
return l > 0 ? l - 1 : -1;
}
//求最大的i,使得a[i] <= key,若不存在,则返回-1
int Equal_Smaller(int a[], int n, int key) {
int m, l = 0, r = n - 1; //闭区间[0, n - 1]
while (l <= r) {
m = l + ((r - l) >> 1);
if (a[m] > key) r = m - 1;
else l = m + 1;
}
return l > 0 ? l - 1 : -1;
}

蔡勒公式

求星期

1
2
3
4
int week(int y,int m,int d){
if(m==1||m==2) m+=12,y=y-1;
return (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7;
}

DLX算法

20150123215406542

  • 精准覆盖问题

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    int a[N];
    struct node{
    int l,r,u,d,col,row;
    };
    struct DLX{
    node p[M];
    int len;
    int size[N],last[N];
    inline void make(int l,int r,int u,int d,int col,int row){len++;p[len].l=l;p[len].r=r;p[len].u=u;p[len].d=d;p[len].col=col;p[len].row=row;}
    inline void ud_del(int x){p[p[x].u].d=p[x].d;p[p[x].d].u=p[x].u;}
    inline void ud_res(int x){p[p[x].u].d=p[p[x].d].u=x;}
    inline void lr_del(int x){p[p[x].l].r=p[x].r;p[p[x].r].l=p[x].l;}
    inline void lr_res(int x){p[p[x].l].r=p[p[x].r].l=x;}
    inline void init(int m){//m - number of column
    len=0;
    p[0].l=p[0].r=p[0].u=p[0].d=0;
    for(int i=1;i<=m;i++){
    size[i]=0;
    last[i]=i;
    make(i-1,p[i-1].r,i,i,i,0);
    lr_res(i);
    }
    }
    inline void add(int row){
    if(a[0]==0)return;
    make(len+1,len+1,last[a[1]],p[last[a[1]]].d,a[1],row);
    ud_res(len);
    size[a[1]]++;
    last[a[1]]=len;
    for(int i=2;i<=a[0];i++){
    make(len,p[len].r,last[a[i]],p[last[a[i]]].d,a[i],row);
    ud_res(len);
    lr_res(len);
    size[a[i]]++;
    last[a[i]]=len;
    }
    }
    inline void del(int x){
    lr_del(x);
    for(int i=p[x].u;i!=x;i=p[i].u){
    for(int j=p[i].l;j!=i;j=p[j].l)ud_del(j),size[p[j].col]--;
    }
    }
    inline void res(int x){
    lr_res(x);
    for(int i=p[x].u;i!=x;i=p[i].u){
    for(int j=p[i].l;j!=i;j=p[j].l)ud_res(j),size[p[j].col]++;
    }
    }
    int dance(int dep){
    if(!p[0].r)return dep;
    int c,mi=inf;
    for(int i=p[0].r;i;i=p[i].r){
    if(size[p[i].col]<mi)mi=size[p[i].col],c=i;
    }
    if(mi==0)return 0;
    del(c);
    for(int i=p[c].u;i!=c;i=p[i].u){
    for(int j=p[i].l;j!=i;j=p[j].l)del(p[j].col);
    int tt=dance(dep+1);
    if(tt)return tt;
    for(int j=p[i].r;j!=i;j=p[j].r)res(p[j].col);
    }
    res(c);
    return 0;
    }
    }dlx;
  • 最小重复覆盖

    允许列重复,求满足覆盖的最小行数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    int a[N];
    struct node{
    int l,r,u,d,col,row;
    };
    int ans;
    struct DLX{
    node p[M];
    int len;
    int size[N],last[N];
    inline void make(int l,int r,int u,int d,int col,int row){len++;p[len].l=l;p[len].r=r;p[len].u=u;p[len].d=d;p[len].col=col;p[len].row=row;}
    inline void ud_del(int x){p[p[x].u].d=p[x].d;p[p[x].d].u=p[x].u;}
    inline void ud_res(int x){p[p[x].u].d=p[p[x].d].u=x;}
    inline void lr_del(int x){p[p[x].l].r=p[x].r;p[p[x].r].l=p[x].l;}
    inline void lr_res(int x){p[p[x].l].r=p[p[x].r].l=x;}
    inline void init(int x){
    len=0;
    p[0].l=p[0].r=p[0].u=p[0].d=0;
    for(int i=1;i<=x;i++){
    size[i]=0;last[i]=i;
    make(i-1,p[i-1].r,i,i,i,0);
    lr_res(i);
    }
    }
    inline void add(int row){
    if(a[0]==0)return;
    make(len+1,len+1,last[a[1]],p[last[a[1]]].d,a[1],row);
    ud_res(len);
    size[a[1]]++;
    last[a[1]]=len;
    for(int i=2;i<=a[0];i++){
    make(len,p[len].r,last[a[i]],p[last[a[i]]].d,a[i],row);
    ud_res(len);
    lr_res(len);
    size[a[i]]++;
    last[a[i]]=len;
    }
    }
    inline void del(int x){
    for(int i=p[x].u;i!=x;i=p[i].u){
    lr_del(i);
    }
    }
    inline void res(int x){
    for(int i=p[x].u;i!=x;i=p[i].u){
    lr_res(i);
    }
    }
    bool vis[N];
    int ex(){//使用 A* 的期望函数来剪枝
    int cnt=0;
    mem0(vis);
    for(int i=p[0].r;i;i=p[i].r){
    if(vis[i])continue;
    cnt++;
    vis[i]=1;
    for(int j=p[i].u;j!=i;j=p[j].u){
    for(int k=p[j].l;k!=j;k=p[k].l)vis[p[k].col]=1;
    }
    }
    return cnt;
    }
    void dance(int dep){
    if(dep+ex()>=ans)return;
    if(!p[0].r){
    ans=min(ans,dep);
    return;
    }
    int first,mi=inf;
    for(int i=p[0].r;i;i=p[i].r){
    if(size[p[i].col]<mi)mi=size[p[i].col],first=i;
    }
    if(mi==0)return;
    for(int i=p[first].u;i!=first;i=p[i].u){
    del(i);
    for(int j=p[i].l;j!=i;j=p[j].l)del(j);
    dance(x+1);
    for(int j=p[i].r;j!=i;j=p[j].r)res(j);
    res(i);
    }
    return ;
    }
    }dlx;

读入挂

  • 整数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    inline void read(ll &x) {
    ll f=1;
    x=0;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
    x*=f;
    }
    inline void write(ll x) {
    if (x < 0) {
    putchar('-');
    x = -x;
    }
    if (x >= 10)write(x / 10);
    putchar(x % 10 + '0');
    }
  • 实数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    inline bool scan_lf(double &num) {
    char in;
    double Dec = 0.1;
    bool IsN = false, IsD = false;
    in = getchar();
    if (in == EOF) return false;
    while (in != '-' && in != '.' && (in < '0' || in > '9')) in = getchar();
    if (in == '-') {
    IsN = true;
    num = 0;
    } else if (in == '.') {
    IsD = true;
    num = 0;
    } else num = in - '0';
    if (!IsD) {
    while (in = getchar(), in >= '0' && in <= '9') {
    num *= 10;
    num += in - '0';
    }
    }
    if (in != '.') {
    if (IsN) num = -num;
    return true;
    } else {
    while (in = getchar(), in >= '0' && in <= '9') {
    num += Dec * (in - '0');
    Dec *= 0.1;
    }
    }
    if (IsN) num = -num;
    return true;
    }

分数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
ll gcd(ll a,ll b){
return b?gcd(b,a%b):abs(a);
}
struct fraction{
ll a, b;
fraction(){}
fraction(ll _a,ll _b){
ll gc=gcd(_a,_b);
a=_a/gc,b=_b/gc;
if(b<0)b=-b,a=-a;
}
bool operator==(const fraction &x)const{
return a==x.a&&b==x.b;
}
bool operator!=(const fraction &x)const{
return !(a==x.a&&b==x.b);
}
bool operator<(const fraction &y)const{
return a * y.b < y.a * b;
}
bool operator<=(const fraction &y)const{
return a * y.b <= y.a * b;
}
fraction operator*(const fraction &y)const{
return fraction(a*y.a,b*y.b);
}
fraction operator+(const fraction &y)const{
return fraction(a * y.b + y.a * b,b*y.b);
}
fraction operator/(const fraction &y)const{
return fraction(a*y.b,b*y.a);
}
fraction operator-(const fraction &y)const{
return fraction(a * y.b - y.a * b,b*y.b);
}
void display(){
if(b==1)printf("%lld\n",a);
else printf("%lld/%lld\n",a,b);
}
};

归并排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void merge_core(int arr[], int begin, int mid, int end){//将两个有序数组合并成一个
int i=begin, j=mid, k=0;
int *tmp = (int*)malloc(sizeof(int)*(end-begin));
for(; i<mid && j<end; tmp[k++]=(arr[i]<arr[j]?arr[i++]:arr[j++]));
for(; i<mid; tmp[k++]=arr[i++]);
for(; j<end; tmp[k++]=arr[j++]);
for(i=begin, k=0; i<end; arr[i++]=tmp[k++]);
free(tmp);
}
void merge_sort(int arr[], int begin, int end){
if (end-begin < 2) return;
int mid = (begin+end)>>1;
merge_sort(arr,begin,mid);
merge_sort(arr,mid,end);
merge_core(arr,begin,mid,end);
}

利用归并排序求逆序对

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int tmpA[100005], cnt = 0;
void merge_sort(int l, int r, int *A) {
if (l >= r) return ;
int mid = (l + r) >> 1;
merge_sort(l, mid, A);
merge_sort(mid + 1, r, A);
int pl = l, pr = mid + 1, tmpp = 0;
while(pl <= mid && pr <= r) {
if (A[pl] <= A[pr]) tmpA[tmpp++] = A[pl++];
else tmpA[tmpp++] = A[pr++], cnt += mid - pl + 1;
}
while(pl <= mid) tmpA[tmpp++] = A[pl++];
while(pr <= r) tmpA[tmpp++] = A[pr++];
for (int i = 0; i < tmpp; i++) A[i + l] = tmpA[i];
}

hash_table

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
const int seed = N;
int tot, First[seed], Next[N], Val[N], Key[N];
void init() {
tot = 0;
mem0(First);
}
void Insert(int key, int val) {
int u = val % seed;
for (int v = First[u]; v; v = Next[v])
if (Val[v] == val && Key[v] < key) {
Key[v] = key;
return;
}
Next[++tot] = First[u];
First[u] = tot;
Val[tot] = val;
Key[tot] = key;
}
int Find(int val) {
int u = val % seed;
for (int v = First[u]; v; v = Next[v])if (Val[v] == val) return Key[v];
return -1;
}

unsigned int ELFhash(char *str) {
unsigned int hash = 0, x = 0;
while (*str) {
hash = (hash << 4) + *str;
if ((x = hash & 0xf0000000) != 0) {
hash ^= (x >> 24);
hash &= ~x;
}
str++;
}
return (hash & 0x7fffffff);
}

unsigned int ELFhash(string str) {
unsigned int hash = 0,x = 0;
for0(i, str.size()) {
hash = (hash << 4) + str[i];
if ((x = hash & 0xf0000000) != 0) {
hash ^= (x >> 24);
hash &= ~x;
}
}
return (hash & 0x7fffffff);
}

快速排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void quick_sort(int l,int r,int m[]){
int i=l,j=r,temp=m[l];
if (l>r) return;
while (i!=j) {
while (m[j]>=temp&&i<j) j--;
while (m[i]<=temp&&i<j) i++;
if (i<j){
int k=m[j];
m[j]=m[i];
m[i]=k;
}
}
m[l]=m[i];
m[i]=temp;
quick_sort(l,i-1,m);
quick_sort(i+1,r,m);
}

曼哈顿距离和切比雪夫距离

曼哈顿距离

$\large dis_m=|x1-x2|+|y1-y2|$

切比雪夫距离

$\large dis_q=max(|x1-x2|,|y1-y2|)$

转换

  • 将坐标 $(x,y)\to(x+y,x-y)$ ,原坐标的 $dis_m$ 等于新坐标的 $dis_q$
  • 将坐标 $(x,y)\to(\frac {x+y}2,\frac {x-y}2)$ ,原坐标的 $dis_q$ 等于新坐标的 $dis_m$

位运算

  • 按位与运算符(&)

    • 运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1;

    • x & (x - 1)
      1.用于消去x最后一位的1
      2.检查n是否为2的幂次
      3.计算在一个 32 位的整数的二进制表式中有多少个 1
      4.如果要将整数A转换为B,需要改变多少个bit位:对A^B进行操作

    • Lowbit(x)

      1
      2
      x&(-x) 
      x&(x^(x-1))
    • 枚举所有集合的子集

      1
      2
      3
      4
      5
      for (int S=1,len=1<<n; S<len; S++){
      for (int T=(S-1)&S; T ; T=(T-1)&S){ //枚举S的所有非空真子集
      //do something.
      }
      }
  • 按位或运算符(|)

    • 运算规则:0|0=0; 0|1=1; 1|0=1; 1|1=1
  • 异或运算符($\text{^}$)

    • 运算规则:$\text{0^0=0; 0^1=1; 1^0=1; 1^1=0;}$
    • 性质:
      1.交换律
      2.结合律 $\text{即(a^b)^c == a^(b^c)}$
      3.对于任何数 x,都有 $\text{x^x=0,x^0=x}$
      4.自反性: $\text{a^b^b=a^0=a;}$
    • $\text{a ^ b ^ b = a}$
      数组中,只有一个数出现一次,剩下都出现两次,找出出现一次的数

线性递推式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
#define SZ(x) ((ll)(x).size())
typedef vector<ll> VI;
typedef pair<ll,ll> PII;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}

namespace linear_seq {
const long long N = 10010;
ll res[N], base[N], _c[N], _md[N];

VI Md;
void mul(ll *a, ll *b, long long k) {
for0(i, k + k) _c[i] = 0;
for0(i, k) if (a[i]) for0(j, k) _c[i + j] =
(_c[i + j] + a[i] * b[j]) % mod;
for (long long i = k + k - 1; i >= k; i--)
if (_c[i])
for0(j, SZ(Md)) _c[i - k + Md[j]] =
(_c[i - k + Md[j]] - _c[i] * _md[Md[j]]) % mod;
for0(i, k) a[i] = _c[i];
}
long long solve(ll n, VI a, VI b) { // a 系数 b 初值 b[n+1]=a[0]*b[n]+...
ll ans = 0, pnt = 0;
long long k = SZ(a);
assert(SZ(a) == SZ(b));
for0(i, k) _md[k - 1 - i] = -a[i];
_md[k] = 1;
Md.clear();
for0(i, k) if (_md[i] != 0) Md.push_back(i);
for0(i, k) res[i] = base[i] = 0;
res[0] = 1;
while ((1ll << pnt) <= n) pnt++;
for (long long p = pnt; p >= 0; p--) {
mul(res, res, k);
if ((n >> p) & 1) {
for (long long i = k - 1; i >= 0; i--) res[i + 1] = res[i];
res[0] = 0;
for0(j, SZ(Md)) res[Md[j]] =
(res[Md[j]] - res[k] * _md[Md[j]]) % mod;
}
}
for0(i, k) ans = (ans + res[i] * b[i]) % mod;
if (ans < 0) ans += mod;
return ans;
}
VI BM(VI s) {
VI C(1, 1), B(1, 1);
long long L = 0, m = 1, b = 1;
for0(n, SZ(s)) {
ll d = 0;
for0(i, L + 1) d = (d + (ll)C[i] * s[n - i]) % mod;
if (d == 0)
++m;
else if (2 * L <= n) {
VI T = C;
ll c = mod - d * powmod(b, mod - 2) % mod;
while (SZ(C) < SZ(B) + m) C.pb(0);
for0(i, SZ(B)) C[i + m] = (C[i + m] + c * B[i]) % mod;
L = n + 1 - L;
B = T;
b = d;
m = 1;
} else {
ll c = mod - d * powmod(b, mod - 2) % mod;
while (SZ(C) < SZ(B) + m) C.pb(0);
for0(i, SZ(B)) C[i + m] = (C[i + m] + c * B[i]) % mod;
++m;
}
}
return C;
}
ll gao(VI a, ll n) {
VI c = BM(a);
c.erase(c.begin());
for0(i, SZ(c)) c[i] = (mod - c[i]) % mod;
return solve(n, c, VI(a.begin(), a.begin() + SZ(c)));
}
}; // namespace linear_seq

//2
struct LinearRecurrence {
using vec = vector<LL>;

static void extand(vec &a, LL d, LL value = 0) {
if (d <= a.size()) return;
a.resize(d, value);
}

static vec BerlekampMassey(const vec &s, LL mod) {
std::function<LL(LL)> inverse = [&](LL a) {
return a == 1 ? 1 : (LL) (mod - mod / a) * inverse(mod % a) % mod;
};
vec A = {1}, B = {1};
LL b = s[0];
for (size_t i = 1, m = 1; i < s.size(); ++i, m++) {
LL d = 0;
for (size_t j = 0; j < A.size(); ++j) {
d += A[j] * s[i - j] % mod;
}
if (!(d %= mod)) continue;
if (2 * (A.size() - 1) <= i) {
auto temp = A;
extand(A, B.size() + m);
LL coef = d * inverse(b) % mod;
for (size_t j = 0; j < B.size(); ++j) {
A[j + m] -= coef * B[j] % mod;
if (A[j + m] < 0) A[j + m] += mod;
}
B = temp, b = d, m = 0;
} else {
extand(A, B.size() + m);
LL coef = d * inverse(b) % mod;
for (size_t j = 0; j < B.size(); ++j) {
A[j + m] -= coef * B[j] % mod;
if (A[j + m] < 0) A[j + m] += mod;
}
}
}
return A;
}

static void exgcd(LL a, LL b, LL &g, LL &x, LL &y) {
if (!b) x = 1, y = 0, g = a;
else {
exgcd(b, a % b, g, y, x);
y -= x * (a / b);
}
}

static LL crt(const vec &c, const vec &m) {
LL n = c.size();
LL M = 1, ans = 0;
for (LL i = 0; i < n; ++i) M *= m[i];
for (LL i = 0; i < n; ++i) {
LL x, y, g, tm = M / m[i];
exgcd(tm, m[i], g, x, y);
ans = (ans + tm * x * c[i] % M) % M;
}
return (ans + M) % M;
}

static vec ReedsSloane(const vec &s, LL mod) {
auto inverse = [](LL a, LL m) {
LL d, x, y;
exgcd(a, m, d, x, y);
return d == 1 ? (x % m + m) % m : -1;
};
auto L = [](const vec &a, const vec &b) {
LL da = (a.size() > 1 || (a.size() == 1 && a[0])) ? (LL) a.size() - 1 : -1000;
LL db = (b.size() > 1 || (b.size() == 1 && b[0])) ? (LL) b.size() - 1 : -1000;
return max(da, db + 1);
};
auto prime_power = [&](const vec &s, LL mod, LL p, LL e) {
// linear feedback shift register mod p^e, p is prime
vector<vec> a(e), b(e), an(e), bn(e), ao(e), bo(e);
vec t(e), u(e), r(e), to(e, 1), uo(e), pw(e + 1);
pw[0] = 1;
for (LL i = pw[0] = 1; i <= e; ++i) pw[i] = pw[i - 1] * p;
for (LL i = 0; i < e; ++i) {
a[i] = {pw[i]}, an[i] = {pw[i]};
b[i] = {0}, bn[i] = {s[0] * pw[i] % mod};
t[i] = s[0] * pw[i] % mod;
if (t[i] == 0) {
t[i] = 1, u[i] = e;
} else {
for (u[i] = 0; t[i] % p == 0; t[i] /= p, ++u[i]);
}
}
for (LL k = 1; k < s.size(); ++k) {
for (LL g = 0; g < e; ++g) {
if (L(an[g], bn[g]) > L(a[g], b[g])) {
ao[g] = a[e - 1 - u[g]];
bo[g] = b[e - 1 - u[g]];
to[g] = t[e - 1 - u[g]];
uo[g] = u[e - 1 - u[g]];
r[g] = k - 1;
}
}
a = an, b = bn;
for (LL o = 0; o < e; ++o) {
LL d = 0;
for (LL i = 0; i < a[o].size() && i <= k; ++i) {
d = (d + a[o][i] * s[k - i]) % mod;
}
if (d == 0) {
t[o] = 1, u[o] = e;
} else {
for (u[o] = 0, t[o] = d; t[o] % p == 0; t[o] /= p, ++u[o]);
LL g = e - 1 - u[o];
if (L(a[g], b[g]) == 0) {
extand(bn[o], k + 1);
bn[o][k] = (bn[o][k] + d) % mod;
} else {
LL coef = t[o] * inverse(to[g], mod) % mod * pw[u[o] - uo[g]] % mod;
LL m = k - r[g];
extand(an[o], ao[g].size() + m);
extand(bn[o], bo[g].size() + m);
for (LL i = 0; i < ao[g].size(); ++i) {
an[o][i + m] -= coef * ao[g][i] % mod;
if (an[o][i + m] < 0) an[o][i + m] += mod;
}
while (an[o].size() && an[o].back() == 0) an[o].pop_back();
for (LL i = 0; i < bo[g].size(); ++i) {
bn[o][i + m] -= coef * bo[g][i] % mod;
if (bn[o][i + m] < 0) bn[o][i + m] -= mod;
}
while (bn[o].size() && bn[o].back() == 0) bn[o].pop_back();
}
}
}
}
return make_pair(an[0], bn[0]);
};

vector<tuple<LL, LL, LL>> fac;
for (LL i = 2; i * i <= mod; ++i)
if (mod % i == 0) {
LL cnt = 0, pw = 1;
while (mod % i == 0) mod /= i, ++cnt, pw *= i;
fac.emplace_back(pw, i, cnt);
}
if (mod > 1) fac.emplace_back(mod, mod, 1);
vector<vec> as;
LL n = 0;
for (auto &&x: fac) {
LL mod, p, e;
vec a, b;
tie(mod, p, e) = x;
auto ss = s;
for (auto &&x: ss) x %= mod;
tie(a, b) = prime_power(ss, mod, p, e);
as.emplace_back(a);
n = max(n, (LL) a.size());
}
vec a(n), c(as.size()), m(as.size());

for (LL i = 0; i < n; ++i) {
for (LL j = 0; j < as.size(); ++j) {
m[j] = get<0>(fac[j]);
c[j] = i < as[j].size() ? as[j][i] : 0;
}
a[i] = crt(c, m);
}
return a;
}

LinearRecurrence(const vec &s, const vec &c, LL mod) :
init(s), trans(c), mod(mod), m(s.size()) {}

LinearRecurrence(const vec &s, LL mod, bool is_prime = true) : mod(mod) {
vec A;
if (is_prime) A = BerlekampMassey(s, mod);
else A = ReedsSloane(s, mod);
if (A.empty()) A = {0};
m = A.size() - 1;
trans.resize(m);
for (LL i = 0; i < m; ++i) {
trans[i] = (mod - A[i + 1]) % mod;
}
reverse(trans.begin(), trans.end());
init = {s.begin(), s.begin() + m};
}

LL calc(LL n) {
if (mod == 1) return 0;
if (n < m) return init[n];
vec v(m), u(m << 1);

LL msk = !!n;
for (LL m = n; m > 1; m >>= 1LL) msk <<= 1LL;
v[0] = 1 % mod;
for (LL x = 0; msk; msk >>= 1LL, x <<= 1LL) {
fill_n(u.begin(), m * 2, 0);
x |= !!(n & msk);
if (x < m) u[x] = 1 % mod;
else { // can be optimized by fft/ntt
for (LL i = 0; i < m; ++i) {
for (LL j = 0, t = i + (x & 1); j < m; ++j, ++t) {
u[t] = (u[t] + v[i] * v[j]) % mod;
}
}
for (LL i = m * 2 - 1; i >= m; --i) {
for (LL j = 0, t = i - m; j < m; ++j, ++t) {
u[t] = (u[t] + trans[j] * u[i]) % mod;
}
}
}
v = {u.begin(), u.begin() + m};
}
LL ret = 0;
for (LL i = 0; i < m; ++i) {
ret = (ret + v[i] * init[i]) % mod;
}
return ret;
}

vec init, trans;
LL mod;
LL m;
};