杰杰的女性朋友

时间限制: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. 【Atcoer】ARC088 E - Papple Sort

    [题目]E - Papple Sort [题意]给定长度为n的小写字母串,只能交换相邻字母,求形成回文串的最小步数.n<=2*10^5. [算法]数学 [题解]官方题解 本题题解中有以下重要的思 ...

  2. 【VIJOS】P1512 SuperBrother打鼹鼠

    [算法]二维树状数组 [题解] 1.树状数组尽量不要出现0,因此所有坐标+1 2.面积求法(默认1开始):(x1,y1)(x2,y2)=sum(x2,y2)-sum(x1-1,y2)-sum(x2,y ...

  3. Java面试中常问的Spring方面问题(涵盖七大方向共55道题,含答案)

    1.一般问题 1.1. 不同版本的 Spring Framework 有哪些主要功能? VersionFeatureSpring 2.5发布于 2007 年.这是第一个支持注解的版本.Spring 3 ...

  4. # 2018高考&自主招生 - 游记

    准备了一整个学期的高考和自主招生终于结束了....从育英出来, 以一个失败者的身份来写游记, 权当为明年的决战提供经验与总结. Day -1, June 5th 下午同学收拾考场, 自己在那里看书.. ...

  5. vue-cli使用说明

    一.安装npm install -g vue-cli 推荐使用国内镜像 先设置cnpm npm install -g cnpm --registry=https://registry.npm.taob ...

  6. sqlite3在Linux下的安装和使用

    自我补充:ubuntu在线安装sqlite3数据库的方法:  系统平台:ubuntu12.04   在ubuntu里面直接使用命令:sudo apt-get install sqlite3 ,出现: ...

  7. android的wake_lock介绍

    Wake Lock是一种锁的机制, 只要有人拿着这个锁,系统就无法进入休眠, 可以被用户态程序和内核获得. 这个锁可以是有超时的或者是没有超时的, 超时的锁会在时间过去以后自动解锁. 如果没有锁了或者 ...

  8. windows下制作debian U盘启动

    制作平台:Windows 7 制作debian版本:debian 7.4 wheezy 1.下载引导镜像,包含三个文件:boot.img.gz(解压备用).initrd.gz 和 vmlinuz. h ...

  9. Linux自身安全SElinux

    查看SELinux状态: 1./usr/sbin/sestatus -v      ##如果SELinux status参数为enabled即为开启状态 SELinux status:         ...

  10. js实现静态页面跳转传参

    最近有个项目: 存静态web服务,一个新闻页面列表出所有新闻摘要信息,然后通过点击新闻详情访问到该新闻的详情页面: 新闻展示的页面通过ajax请求接口获取到新闻的摘要信息,预计想通过id的方式访问到新 ...