@codechef - BIKE@ Chef and Bike
@description@
输入 n(n ≤ 22) 个点,m(m ≤ 8000) 个边。每个边连接着点 (si, ei),有两个长度 fi, ri。
问对于每个点 k,有多少条路径(不一定是简单路径)由 t (t ≤ 10^9) 条边组成,从 k 开始,并且以 k 结束;并且路径上所有边 f 的和 mod n 为 x;并且路径上所有边 r 的和 mod (n − 1) 为 y。
对于每一个 (x, y) 都要计算。
方案数 mod 1163962801 输出。
input
输入的第一行包含三个整数 n、m 和 t。n, m, t 的含义如上,注意 n 是点数,也是模数。如果重复经过同一条边,需要计算两次。
之后的 m 行里,每一行表示一条边。其中第 i 行包含四个整数,分别代表 si, ei, fi, ri。含义如上。
可能有重边自环。
output
输出被分为 n 个部分。其中第 k 个部分 (1 ≤ k ≤ n) 包含 n 行,而每一行包含 n − 1 个整数。
第 k 个输出部分的第 i 行的第 j 个数应当表示从点 k 出发,走过 t 条边之后回到点 k,路径上所有边 f 的和 mod n 为 i;并且路径上所有边 r 的和 mod (n − 1) 为 j。
输出的所有数字都应当对 1163962801 取模。
sample input
3 6 6
1 2 0 0
2 1 1 1
1 3 1 2
3 1 2 1
2 3 5 5
3 2 10 10
sample output
1 5
0 10
1 5
1 5
0 10
1 5
1 8
0 10
1 2
@solution@
首先观察到 n 的范围很小,t 的范围很大,并且可以经过重复的边。不难想到使用矩阵加速。
一个很 naive 的想法是,我们对于矩阵的每一个位置 (i, j) 记录 n*(n-1) 个二元组 (x, y),表示从 i 到 j 路径上所有边 f 的和 mod n 为 x,r 的和 mod (n − 1) 为 y 的方案数。
这样做矩阵乘法 \(C = A*B\) 的时候,\(C(i, j) = \sum A(i, k)*B(k, j)\) 实际上就是 \(C(i, j, (x+p) \mod n, (y+q) \mod (n-1)) = \sum(A(i, k, x, y) * B(k, j, p, q))\)。
要做 \(O(n^3)\) 次乘法,每次乘法 \(O(n^4)\)。时间复杂度 \(O(n^7*log k)\)。虽然 n 很小但还是太慢了。
观察我们乘法的转移形式,不难发现它是一个循环卷积的形式,可以使用 fft 优化。
优化过后每次乘法只需要 \(O(n^2*log n)\) 的时间,时间复杂度降为 \(O(n^5*log n*log k)\)。
但是注意到模数不是 998244353 而是 1163962801,所以这里的 fft 必须要使用一些常数较大的技巧来避免溢出。
所以实际运行时效果远不如 \(O(n^5*log n*log k)\) 那么优秀。
考虑我们平常使用多项式作快速幂,是将其转为点值形式,使用点值做快速幂。这个地方是否也可以运用这一方法呢。
对于长度为 n 的循环卷积,无法将其长度拓展为 2 的幂,所以无法使用一般的 fft。
但是,代入 n 次单位根很多性质依然可以满足。或者说,除了不能使用分治进行 fft,其他性质都可以满足。
注意到这个地方的 n 很小,我们可以直接暴力 \(O(n^2)\) 求值,暴力 \(O(n^2)\) 还原。
观察模数 mod = 1163962801。想一想为什么可以使用 p = 998244353 进行数论变换,因为 p-1 恰好是 2^23 的倍数,所以它有 2^x(x ≤ 23) 次单位根。
对 mod - 1 进行质因数分解,它等于 \(2^4*3^2*5^2*7*11*13*17*19\)。我们发现它是 1~22 所有数字的公倍数,因此它有 1~22 次单位根。
最后一个问题,这个地方是一个二维的卷积形式。
因此,我们求值时是代入一个二元组 \((w_n^i, w_{n-1}^j)\),一共有 n*(n-1) 对二元组要求值。
最后逆变换还原时,插值 \((w_n^{-i}, w_{n-1}^{-j})\) 即可。直观理解起来不难。
时间复杂度为 \(O(n^5*log k)\)。
@accepted code@
#include<cstdio>
const int G = 46;
const int MAXN = 22 + 5;
const int MAXM = 10000 + 5;
const int MOD = 1163962801;
inline int add(int x, int y) {return (1LL*x + 1LL*y)%MOD;}
inline int mul(int x, int y) {return 1LL*x*y%MOD;}
int pow_mod(int b, int p) {
int ret = 1;
while( p ) {
if( p & 1 ) ret = mul(ret, b);
b = mul(b, b);
p >>= 1;
}
return ret;
}
struct matrix{
int m[MAXN][MAXN], r, c;
friend matrix operator * (const matrix &A, const matrix &B) {
matrix C; C.r = A.r, C.c = B.c;
for(int i=0;i<C.r;i++)
for(int j=0;j<C.c;j++) {
C.m[i][j] = 0;
for(int k=0;k<A.c;k++) {
C.m[i][j] = add(C.m[i][j], mul(A.m[i][k], B.m[k][j]));
}
}
return C;
}
};
matrix mpow(matrix A, int p) {
matrix ret; ret.r = ret.c = A.r;
for(int i=0;i<A.r;i++)
for(int j=0;j<A.c;j++)
ret.m[i][j] = (i == j);
while( p ) {
if( p & 1 ) ret = ret * A;
A = A * A;
p >>= 1;
}
return ret;
}
void func(int a[], int n) {
a[0] = 1, a[1] = pow_mod(G, (MOD - 1)/n);
for(int i=2;i<n;i++) a[i] = mul(a[i - 1], a[1]);
}
int wx[MAXN], wy[MAXN];
int u[MAXM], v[MAXM], x[MAXM], y[MAXM];
int t, n, m;
matrix get_matrix(int i, int j) {
matrix A; A.r = A.c = n;
for(int k=0;k<A.r;k++)
for(int l=0;l<A.c;l++)
A.m[k][l] = 0;
for(int k=1;k<=m;k++)
A.m[u[k]][v[k]] = add(A.m[u[k]][v[k]], mul(pow_mod(wx[i], x[k]), pow_mod(wy[j], y[k])));
return A;
}
int f[MAXN][MAXN][MAXN];
int ans[MAXN][MAXN];
void func2(int i) {
for(int j=0;j<n;j++)
for(int k=0;k<n-1;k++)
ans[j][k] = 0;
for(int j=0;j<n;j++)
for(int k=0;k<n-1;k++)
for(int p=0;p<n;p++)
for(int q=0;q<n-1;q++) {
ans[j][k] = add(ans[j][k], mul(f[i][p][q], mul(pow_mod(wx[j], n-p), pow_mod(wy[k], (n-1)-q))));
}
int inv = pow_mod(n*(n - 1), MOD - 2);
for(int j=0;j<n;j++)
for(int k=0;k<n-1;k++)
printf("%d%c", mul(ans[j][k], inv), (k + 1 == n - 1) ? '\n' : ' ');
}
int main() {
scanf("%d%d%d", &n, &m, &t);
for(int i=1;i<=m;i++) {
scanf("%d%d%d%d", &u[i], &v[i], &x[i], &y[i]);
u[i]--, v[i]--, x[i] %= n, y[i] %= (n-1);
}
func(wx, n), func(wy, n - 1);
for(int i=0;i<n;i++)
for(int j=0;j<n-1;j++) {
matrix M = mpow(get_matrix(i, j), t);
for(int k=0;k<n;k++)
f[k][i][j] = M.m[k][k];
}
for(int i=0;i<n;i++)
func2(i);
}
@details@
这道题的模数,加法刚好溢出 int。
我就说为什么它会出现负数……
2017 冬令营的老题了……
@codechef - BIKE@ Chef and Bike的更多相关文章
- 【Codechef】Chef and Bike(二维多项式插值)
something wrong with my new blog! I can't type matrixs so I come back. qwq 题目:https://www.codechef.c ...
- [Codechef CHSTR] Chef and String - 后缀数组
[Codechef CHSTR] Chef and String Description 每次询问 \(S\) 的子串中,选出 \(k\) 个相同子串的方案有多少种. Solution 本题要求不是很 ...
- 【CodeChef】Chef and Graph Queries
Portal --> CC Chef and Graph Queries Solution 快乐数据结构题(然而好像有十分优秀的莫队+可撤销并查集搞法qwq) 首先考虑一种方式来方便一点地..计 ...
- [CodeChef - GERALD07 ] Chef and Graph Queries
Read problems statements in Mandarin Chineseand Russian. Problem Statement Chef has a undirected gra ...
- CodeChef CHEFSOC2 Chef and Big Soccer 水dp
Chef and Big Soccer Problem code: CHEFSOC2 Tweet ALL SUBMISSIONS All submissions for this prob ...
- Codechef FNCS Chef and Churu
Disciption Chef has recently learnt Function and Addition. He is too exited to teach this to his fri ...
- CodeChef - FNCS Chef and Churu(分块)
https://vjudge.net/problem/CodeChef-FNCS 题意: 思路: 用分块的方法,对每个函数进行分块,计算出该分块里每个数的个数,这样的话也就能很方便的计算出这个分块里所 ...
- 【xsy2111】 【CODECHEF】Chef and Churus 分块+树状数组
题目大意:给你一个长度为$n$的数列$a_i$,定义$f_i=\sum_{j=l_i}^{r_i} num_j$. 有$m$个操作: 操作1:询问一个区间$l,r$请你求出$\sum_{i=l}^{r ...
- codechef T2 Chef and Sign Sequences
CHEFSIGN: 大厨与符号序列题目描述 大厨昨天捡到了一个奇怪的字符串 s,这是一个仅包含‘<’.‘=’和‘>’三种比较符号的字符串. 记字符串长度为 N,大厨想要在字符串的开头.结尾 ...
随机推荐
- LintCode_50 数组剔除元素后的乘积
题目 给定一个整数数组A. 定义B[i] = A[0] * ... * A[i-1] * A[i+1] * ... * A[n-1], 计算B的时候请不要使用除法. 样例 给出A=[1, 2, 3], ...
- python 数据标准化
- 【模板】矩阵快速幂 洛谷P2233 [HNOI2002]公交车路线
P2233 [HNOI2002]公交车路线 题目背景 在长沙城新建的环城公路上一共有8个公交站,分别为A.B.C.D.E.F.G.H.公共汽车只能够在相邻的两个公交站之间运行,因此你从某一个公交站到另 ...
- Mysql的CMD操作
一.MySQL登录和退出——在CMD模式操作 l 语法格式:mysql.exe –h主机名 –u用户名 –p密码 l 参数说明: mysql.exe是mysql服务器的主应用程序. -h代 ...
- xmlns详解(转载)
我们经常会在网页中碰到形如<html xmlns=”http://www.w3.org/2001/xhtml”>这样的代码, 或在是android 编码中的main.xml中看到形如< ...
- 强力Django+杀手级xadmin开发在线教育网站
强力Django+杀手级xadmin开发在线教育网站采用 Python3.7全新开发 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的 ...
- ie8或9下ajax跨域问题
ie8或9下ajax跨域支持,添加如下代码 <!--[if (IE 8)|(IE 9)]><script src="https://cdn.bootcss.com/jque ...
- Percona XtraBackup 完全及增量备份与恢复的方法
安装及备份.恢复实现 安装:其最新版的软件可从 http://www.percona.com/software/percona-xtrabackup/ 获得.本文基于CentOS6.x的系统,因此,直 ...
- Mysql+php报错原因
SQL syntax --语法错误,看near,错误会在near后引号中的内容 的附近 Table/Database....... dosen't existes ---表/库(库名/表名) 不存在 ...
- SpringMvc表单标签库
HTML密码框 <td><form:label path="password">密码:</form:label></td><t ...