杰杰的女性朋友

时间限制:10s      空间限制:256MB

题目描述

   杰杰是魔法界的一名传奇人物。他对魔法具有深刻的洞察力,惊人的领悟力,以及令人叹为观止的创造力。自从他从事魔法竞赛以来,短短几年时间,就已经成为 世界公认的实力最强的魔法选手之一。更让人惊叹的是,他几乎没有借助外界力量,完全凭借自己的努力达到了普通人难以企及的高度。在最近的世界魔法奥林匹克 竞赛上,他使用高超的魔法本领,一路过关斩将,在最后时刻一举击败了前冠军“旅行者”,获得了魔法界最高的荣耀:女神奖杯!女神奖杯可不是一个普通的奖 杯,她能够帮杰杰实现一个愿望。
  杰杰本着实事求是的态度,审时度势,向女神奖杯提出了自己的愿望:想要一个女性朋友。

  杰杰的愿望实现了,可是女性朋友却和他不在一个城市。杰杰想要知道:如果要到达女性朋友的所在城市,有多少种方案供他选择?
  杰杰所在的世界有n个城市,从1到n进行编号。任意两个城市都通过有向道路连接。每个城市u有k个入点权:in[u][1],in[u]
[2]...in[u][k],有k个出点权:ou[u][1],ou[u][2]...ou[u][k]。对于任意两个城市(u,v)(u可以等于
v),u到v的道路条数为(ou[u][1]*in[v][1]+ou[u][2]*in[v][2]+...+ou[u][k]*in[v][k])
条。杰杰有m次询问,每次询问由三元组(u,v,d)构成,询问从u城市通过不超过d条道路到达v城市的方案数。
  为了温柔的杰杰和他的女性朋友的美好未来,帮助他解答这个问题吧。


输入格式

  第一行读入两个正整数n,k,含义如题所示。接下来n行每行2k个整数,第i行代表第i个城市,前k个整数代表i号城市的出点权,后k个整数代表i号城市的入点权:
  ou[i][1],ou[i][2],…,ou[i][k],in[i][1],in[i][2],…,in[i][k]
  接下来一个整数m,表示m个询问。
  接下来m行,每行三个整数:u,v,d,询问从u城市通过不超过d条道路到达v城市的方案数。
  将每个方案所经过的道路,按顺序写成一个序列(序列可以为空)。两个方案不同,当且仅当他们的道路序列不完全相同。


输出格式

  对于每个询问,输出一个方案数。由于答案可能太大,输出其除以1000000007后的余数。


样例输入

5 2
2 5 4 3
7 9 2 4
0 1 5 2
6 3 9 2
2147483647 1000000001 233522 788488
10
1 1 0
2 2 1
2 4 5
4 3 10
3 4 50
1 5 1000
3 5 1000000000
1 2 500000000
4 5 2147483647
3 1 2147483647

样例输出

1
51
170107227
271772358
34562176
890241289
8516097
383966304
432287042
326522835

提示

数据规模和约定
n<=1000
k<=20
m<=50

  保证1<=u, v<=n, 其它所有读入为不超过2147483647的非负整数


题目来源

By 佚名提供

FJOI2018一试就是直接使用了这道清华集训原题。

首先列出DP状态转移方程,$f[t][i]$表示走了$t$步之后到达$i$节点的方案数:$$f[t][i]=\sum\limits_{j=1}^{n} (f[t-1][j]*\sum\limits_{l=1}^{k} O_{j,l}*I_{i,l})$$

这样做的复杂度是$O(n^2d)$,而 $d \leqslant 2^{31}-1$,显然无法在时限内出解。

观察这个转移方程,不难看出这是裸的矩阵快速幂,于是可以在$O(n^3 \log d)$时间内出解。

然而这个复杂度仍然不够优,事实上,连FJOI2018现场最低的一档部分分都无法通过。

于是需要进一步观察矩阵的性质:

$f$是一个$1*n$的矩阵,$O$是一个$n*k$的矩阵,$I$是$n*k$的,而$C=OI^T$所以$C$是$n*n$的。由数据范围可知,如果我们能将$n*n$的矩阵乘法优化到$k*k$,那么就可以通过全部数据。

不难发现答案$$f[d]=f[0]*C^d=f[0]*(OI^T)^d=f[0]*O*(I^TO)^{d-1}*I$$而$I^TO$是$k*k$的,所以我们只要求$D=I^TO$就好了。

但是还有一个问题,题目要求的是$$\sum\limits_{i=0}^{d} f[i]$$ 也就是$$f[0]+f[0]*O{(I^{T}O)}^{0}I +f[0]*O(I^TO)^{1}I+ \ldots +f[0]*O(I^TO)^{d-1}I\\=f[0]*O*(\sum\limits_{i=0}^{d-1}D^{i})*I$$这种涉及到幂和的问题就不能直接使用矩阵快速幂解决。

我们可以首先预处理出所有$A_i=D^{2^i} (i=0,1,2,...)$,$B_i=\sum\limits_{j=1}^{2^i} D^{j} (i=0,1,2,...) $,故$B_i=B_{i-1}A_i$

这样我们有$$\sum\limits_{i=0}^{d-1}D^{i}=E+(D+D^{1}+...+D^{d_1})+(D^{d_{1}+1}+D^{d_{1}+2}+...+D^{d_1+d_2})+...$$其中$d_i$为d的二进制第i个1代表的数。$E$为单位矩阵

对于每个括号分别考虑,$$D+D^{1}+...+D^{d_1}=B^{d_1}$$$$D^{d_{1}+1}+D^{d_{1}+2}+...+D^{d_1+d_2}=(B_{d_2}*A_{d_1})$$

以此类推,就可以得到最终的答案。代码片段如下:

    rep(i,,m) rep(j,,m) B[][i][j]=A[][i][j];
rep(i,,L-){
mul(A[i],A[i]);
rep(j,,m) rep(k,,m) A[i+][j][k]=C[j][k];
rep(j,,m) up(A[i][j][j],);
mul(B[i],A[i]);
rep(j,,m) rep(k,,m) B[i+][j][k]=C[j][k];
rep(j,,m) up(A[i][j][j],P-);
}
 void cal(int n){
rep(i,,m) rep(j,,m) G[i][j]=S[i][j]=;
if(n<)return;
rep(i,,m) S[i][i]=G[i][i]=;
for(int i=; i<L; i++) if(n>>i&){
mul(B[i],G); rep(j,,m) rep(k,,m) up(S[j][k],C[j][k]);
mul(G,A[i]); rep(j,,m) rep(k,,m) G[j][k]=C[j][k];
}
}

剩下的只要根据输入数据建矩阵即可

 #include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=l; i<=r; i++)
using namespace std; const int N=,K=,L=,P=;
int n,m,q,x,y,z,ans,O[N][K],I[N][K],f[N];
int S[K][K],G[K][K],A[L][K][K],B[L][K][K],C[K][K]; void up(int &a,int b){ a+=b; if(a>=P)a-=P; }
void mul(int a[][K],int b[][K]){
rep(i,,m) rep(j,,m) C[i][j]=;
rep(i,,m) rep(j,,m) rep(k,,m) C[i][k]=(C[i][k]+1ll*a[i][j]*b[j][k])%P;
} void cal(int n){
rep(i,,m) rep(j,,m) G[i][j]=S[i][j]=;
if(n<)return;
rep(i,,m) S[i][i]=G[i][i]=;
for(int i=; i<L; i++) if(n>>i&){
mul(B[i],G); rep(j,,m) rep(k,,m) up(S[j][k],C[j][k]);
mul(G,A[i]); rep(j,,m) rep(k,,m) G[j][k]=C[j][k];
}
} int main(){
freopen("bzoj3583.in","r",stdin);
freopen("bzoj3583.out","w",stdout);
scanf("%d%d",&n,&m);
rep(i,,n){
rep(j,,m) scanf("%d",&O[i][j]);
rep(j,,m) scanf("%d",&I[i][j]);
}
rep(k,,n) rep(i,,m) rep(j,,m) A[][i][j]=(A[][i][j]+1ll*I[k][i]*O[k][j])%P;
rep(i,,m) rep(j,,m) B[][i][j]=A[][i][j];
rep(i,,L-){
mul(A[i],A[i]);
rep(j,,m) rep(k,,m) A[i+][j][k]=C[j][k];
rep(j,,m) up(A[i][j][j],);
mul(B[i],A[i]);
rep(j,,m) rep(k,,m) B[i+][j][k]=C[j][k];
rep(j,,m) up(A[i][j][j],P-);
}
scanf("%d",&q);
while (q--){
scanf("%d%d%d",&x,&y,&z); cal(z-);
rep(i,,m) f[i]=; ans=;
rep(i,,m) rep(j,,m) f[i]=(f[i]+1ll*O[x][j]*S[j][i])%P;
rep(i,,m) ans=(ans+1ll*f[i]*I[y][i])%P;
printf("%d\n",(ans+(x==y))%P);
}
return ;
}

[BZOJ3583]杰杰的女性朋友(矩阵快速幂)的更多相关文章

  1. Codeforces 954 dijsktra 离散化矩阵快速幂DP 前缀和二分check

    A B C D 给你一个联通图 给定S,T 要求你加一条边使得ST的最短距离不会减少 问你有多少种方法 因为N<=1000 所以N^2枚举边数 迪杰斯特拉两次 求出Sdis 和 Tdis 如果d ...

  2. hdu5171(矩阵快速幂)

    传送门:GTY's birthday gift 题意:GTY的朋友ZZF的生日要来了,GTY问他的基友送什么礼物比较好,他的一个基友说送一个可重集吧!于是GTY找到了一个可重集S,GTY能使用神犇魔法 ...

  3. BestCoder Round #29——A--GTY's math problem(快速幂(对数法))、B--GTY's birthday gift(矩阵快速幂)

    GTY's math problem Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Other ...

  4. 矩阵快速幂 HDU 4565 So Easy!(简单?才怪!)

    题目链接 题意: 思路: 直接拿别人的图,自己写太麻烦了~ 然后就可以用矩阵快速幂套模板求递推式啦~ 另外: 这题想不到或者不会矩阵快速幂,根本没法做,还是2013年长沙邀请赛水题,也是2008年Go ...

  5. 51nod 算法马拉松18 B 非010串 矩阵快速幂

    非010串 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 如果一个01字符串满足不存在010这样的子串,那么称它为非010串. 求长度为n的非010串的个数.(对1e9+7取模) ...

  6. 51nod 1113 矩阵快速幂

    题目链接:51nod 1113 矩阵快速幂 模板题,学习下. #include<cstdio> #include<cmath> #include<cstring> ...

  7. 【66测试20161115】【树】【DP_LIS】【SPFA】【同余最短路】【递推】【矩阵快速幂】

    还有3天,今天考试又崩了.状态还没有调整过来... 第一题:小L的二叉树 勤奋又善于思考的小L接触了信息学竞赛,开始的学习十分顺利.但是,小L对数据结构的掌握实在十分渣渣.所以,小L当时卡在了二叉树. ...

  8. HDU5950(矩阵快速幂)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5950 题意:f(n) = f(n-1) + 2*f(n-2) + n^4,f(1) = a , f(2 ...

  9. 51nod 1126 矩阵快速幂 水

    有一个序列是这样定义的:f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7. 给出A,B和N,求f(n)的值. Input 输 ...

随机推荐

  1. PHP做文件限速下载

    <?php include("DBDA.class.php"); $db = new DBDA(); $bs = $_SERVER["QUERY_STRING&qu ...

  2. 【洛谷 P3227】 [HNOI2013]切糕(最小割)

    题目链接 每层每个位置向下一层这个位置连边,流量为下一层这个位置的\(f\),源点向第一层连,流量第一层每个位置的费用,最后一层向汇点连,流量\(INF\). 这样就得到了\(P*Q\)条链,不考虑\ ...

  3. HDU 5995 Kblack loves flag (模拟)

    题目链接 Problem Description Kblack loves flags, so he has infinite flags in his pocket. One day, Kblack ...

  4. HDU 2516 取石子游戏 (找规律)

    题目链接 Problem Description 1堆石子有n个,两人轮流取.先取者第1次可以取任意多个,但不能全部取完.以后每次取的石子数不能超过上次取子数的2倍.取完者胜.先取者负输出" ...

  5. arch点击硬盘无法挂载

    出现问题如下 在使用xfce4桌面的时候在点击硬盘图标时可以挂载虽然要求你输入root密码 但是在使用openbox的时候点击硬盘图标却出现如下提示,权限的问题 Not authorized to p ...

  6. static作用(修饰函数、局部变量、全局变量)转自http://www.cnblogs.com/stoneJin/archive/2011/09/21/2183313.html

    static作用(修饰函数.局部变量.全局变量) 在C语言中,static的字面意思很容易把我们导入歧途,其实它的作用有三条. (1)先来介绍它的第一条也是最重要的一条:隐藏. 当我们同时编译多个文件 ...

  7. Nginx实现404页面的几种方法【转】

    一个网站项目,肯定是避免不了404页面的,通常使用Nginx作为Web服务器时,有以下集中配置方式,一起来看看. 第一种:Nginx自己的错误页面 Nginx访问一个静态的html 页面,当这个页面没 ...

  8. tp 框架 利用反射实现对象调用方法

    <?php class Person{ public $name="xiaoming"; function say(){ echo "i am ".$th ...

  9. [How to] HBase的bulkload使用方法

    1.简介 将数据插入HBase表中的方法很多,我们可以通过TableOutputFormat以Mapreduce on HBase的方式将数据插入,也可以单纯的使用客户端API将数据插入.但是以上方法 ...

  10. Guava cache功能简介(转)

    原文链接:http://ifeve.com/google-guava-cachesexplained/ 范例 LoadingCache<Key, Graph> graphs = Cache ...