@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的更多相关文章

  1. 【Codechef】Chef and Bike(二维多项式插值)

    something wrong with my new blog! I can't type matrixs so I come back. qwq 题目:https://www.codechef.c ...

  2. [Codechef CHSTR] Chef and String - 后缀数组

    [Codechef CHSTR] Chef and String Description 每次询问 \(S\) 的子串中,选出 \(k\) 个相同子串的方案有多少种. Solution 本题要求不是很 ...

  3. 【CodeChef】Chef and Graph Queries

    Portal --> CC Chef and Graph Queries Solution 快乐数据结构题(然而好像有十分优秀的莫队+可撤销并查集搞法qwq) 首先考虑一种方式来方便一点地..计 ...

  4. [CodeChef - GERALD07 ] Chef and Graph Queries

    Read problems statements in Mandarin Chineseand Russian. Problem Statement Chef has a undirected gra ...

  5. CodeChef CHEFSOC2 Chef and Big Soccer 水dp

    Chef and Big Soccer   Problem code: CHEFSOC2 Tweet     ALL SUBMISSIONS All submissions for this prob ...

  6. Codechef FNCS Chef and Churu

    Disciption Chef has recently learnt Function and Addition. He is too exited to teach this to his fri ...

  7. CodeChef - FNCS Chef and Churu(分块)

    https://vjudge.net/problem/CodeChef-FNCS 题意: 思路: 用分块的方法,对每个函数进行分块,计算出该分块里每个数的个数,这样的话也就能很方便的计算出这个分块里所 ...

  8. 【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 ...

  9. codechef T2 Chef and Sign Sequences

    CHEFSIGN: 大厨与符号序列题目描述 大厨昨天捡到了一个奇怪的字符串 s,这是一个仅包含‘<’.‘=’和‘>’三种比较符号的字符串. 记字符串长度为 N,大厨想要在字符串的开头.结尾 ...

随机推荐

  1. python基础--GIL全局解释器锁、Event事件、信号量、死锁、递归锁

    ps:python解释器有很多种,最常见的就是C python解释器 GIL全局解释器锁: GIL本质上是一把互斥锁:将并发变成串行,牺牲效率保证了数据的安全 用来阻止同一个进程下的多个线程的同时执行 ...

  2. Redis分布式锁的实现及注意事项

    一.前言 分布式锁一般有三种实现方式: 1. 数据库乐观锁: 2. 基于Redis的分布式锁: 3. 基于ZooKeeper的分布式锁. 本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上 ...

  3. Git push 出错 [The remote end hung up unexpectedly] - 简书

    one day,my teamate using git push and occured this error. $ git push Counting objects: 2332669, done ...

  4. Android的ADB学习笔记

    1.ADB的常用命令   Pull命令:adb -e|-d pull {文件的路径} {获取文件路径} 2. 文件操作的基本命令 ls -al:显示当下目录下用户对文件的操作权限.  = la -al ...

  5. OpenSmtp 发送邮件

    1.采用发送一个简单邮件 示例: private int smtpPort; private string smtpHost; private int recieveTimeout; private ...

  6. 转: CentOS上安装LAMP之第一步:Apache环境及安装过程报错解决方案(纯净系统环境)

    传送门:http://blog.csdn.net/zhangatle/article/details/77416996  小心坑!填完就懂怎么安装了 Note:要从零开始搭建,就不要嫌中间遇到各种问题 ...

  7. web前端学习(四)JavaScript学习笔记部分(1)-- JavaScript基础教程

    1.JavaScript基础教程 1.1.Javascript基础-介绍.实现.输出 1.1.1.JavaScript是互联网上最流行的脚本语言,这门语言可用于web和HTML,更可广泛用于服务端.p ...

  8. 一次web请求发生的神奇故事

    网络时代来临的时候,一个食指的点击就能解决很多问题! 那么当你的食指点击的时候,都发生了哪些神奇的事情呢?下面从几个角度为你做一个指引 1. 网络角度:一次网络请求是如何实现的 2. 浏览器角度:He ...

  9. CSS hack处理

    css hack指各版本及各品牌浏览器之间对CSS解释后出现网页内容的误差. 各浏览器CSS解析: 1.大部分特殊字符IE浏览器支持,其他主流浏览器firefox,chrome,opera,safar ...

  10. hive-oracle-常用分析函数-窗口函数

    常用的分析函数如下所列: row_number() over(partition by ... order by ...)rank() over(partition by ... order by . ...