@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. IO流7 --- FileWriter写出数据的操作 --- 技术搬运工(尚硅谷)

    FileWriter字符输出 @Test public void test3(){ File file = new File("hello1.txt"); FileWriter f ...

  2. Docker Mysql部署

    1.下载tomcat镜像 docker pull mysql 2.启动容器 docker run -d --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD ...

  3. dom4解析 XML

    Java XML解析工具 dom4j介绍及使用实例 Java XML解析工具 dom4j介绍及使用实例 dom4j介绍 dom4j的项目地址:http://sourceforge.net/projec ...

  4. Nginx 函数解析之ngx_http_get_forwarded_addr_internal

    static ngx_int_t ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r, ngx_addr_t *addr, u_cha ...

  5. R语言可视化二

    Lattice绘图系统 Lattice包: xyplot(散点图)/ bwplot / histrogram(柱状图)/ stripplot / dotplot(点图) 格式:xyplot(y~x | ...

  6. js中this指向学习总结

      在面向对象的语言中(例如Java,C#等),this 含义是明确且具体的,即指向当前对象.一般在编译期绑定. 然而js中this 是在运行期进行绑定的,这是js中this 关键字具备多重含义的本质 ...

  7. spring源码学习之默认标签的解析(一)

    继续spring源码的学习之路,现在越来越觉得这个真的很枯燥的,而且我觉得要是自己来看源码,真的看不下去,不是没有耐心,而是真的没有头绪,我觉得结合着书来看,还是很有必要的,最起码大致的流程是能够捋清 ...

  8. 【python之路20】函数作为参数

    1.函数可以作为参数 1)函数名相当于变量指向函数 2)函数名后面加括号表示调用函数 #!usr/bin/env python # -*- coding:utf-8 -*- def f1(args): ...

  9. Chrome进行多分辨率测试

    在Web开发中,经常需要在不同的浏览器分辨率下进行测试,以确认页面是否可以适应不同的分辨率. 下载Resolution Test扩展程序 下载地址:http://pan.baidu.com/s/1gf ...

  10. JS---案例:拖曳对话框

    案例:拖曳对话框 ps: 实际没有要拖曳登录框的需求,只是演示拖曳的这个效果 1. 获取超链接,注册点击事件,显示登陆框和遮挡层 2. 获取关闭,注册点击事件,隐藏登陆框和遮挡层 3. 按下鼠标,移动 ...