http://210.33.19.103/problem/2174

很显然是矩阵快速幂的题,设有in和ou矩阵,设in矩阵的转置为in'

显然可以直接暴力求出任意两点间走一步路径条数,然后求其d次幂,但是这样子复杂度不对

注意到设任意两点间走一步路径条数的矩阵为A,那么A=ou*in',A^d=(ou*in')^d=ou*(in'*ou)^(d-1)*in'(当然d==1时直接特判掉)

in'*ou就是一个K*K的矩阵了,复杂度很对的样子

好像还有点不对。。。题意要求的是前缀和,问题也不大,

设P=in'*ou

题目要求的是ou*P^0*in'+ou*P^1*in'+..+ou*P^(d-1)*in'=ou*(P^0+P^1+..+P^(d-1))*in'

这个P^0+P^1+..+P^(d-1),搞一个矩阵套矩阵可以算(的确是可以用的23333)

搞两个矩阵X,Y,X=(I,I),Y是一个2*2的矩阵,第一行为(P,P),第二行为(0,I)(I表示K阶单位矩阵,0表示K阶零矩阵)

那么求Z=X*Y^(d-1),Z的第一行第二列的值即为P^0+P^1+..+P^(d-1)

(以上与求值的前缀和的方法是一样的)

明明是思路很清晰的题啊,然而我又是一天被续掉了。。。

鬼畜卡常题啊。。。

此题最好,最正确的方法是不用任何结构体,手写所有矩阵相乘

绝对不能用vector来存不同大小的矩阵!不然会T飞

绝对不要尝试在这类地方用模板类来实现嵌套矩阵!搞不出来的

嵌套矩阵很难写,常数又大,后来我干脆把这个嵌套的矩阵拆开(2*2的矩阵,其中每个元素是K*K的矩阵,就拆成(2*K)*(2*K)的矩阵),目前可以确认是对的

O3卡过代码:

  1. #pragma GCC optimize(3)
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<vector>
  6. #include<cassert>
  7. using namespace std;
  8. #define fi first
  9. #define se second
  10. #define mp make_pair
  11. #define pb push_back
  12. typedef long long ll;
  13. typedef unsigned long long ull;
  14. typedef pair<int,int> pii;
  15. //#define assert(x)
  16. const int md=;
  17. struct M_NN
  18. {
  19. int d[][];int x,y;
  20. void resize(int a,int b)
  21. {
  22. x=a;y=b;
  23. memset(d,,sizeof(d));
  24. //d.clear();
  25. //d.resize(x+1);
  26. //for(int i=1;i<=x;i++) d[i].resize(y+1);
  27. }
  28. };
  29. struct M_NK
  30. {
  31. int d[][];int x,y;
  32. void resize(int a,int b)
  33. {
  34. x=a;y=b;
  35. memset(d,,sizeof(d));
  36. //d.clear();
  37. //d.resize(x+1);
  38. //for(int i=1;i<=x;i++) d[i].resize(y+1);
  39. }
  40. };
  41. struct M_KN
  42. {
  43. int d[][];int x,y;
  44. void resize(int a,int b)
  45. {
  46. x=a;y=b;
  47. memset(d,,sizeof(d));
  48. //d.clear();
  49. //d.resize(x+1);
  50. //for(int i=1;i<=x;i++) d[i].resize(y+1);
  51. }
  52. };
  53. struct M_KK
  54. {
  55. int d[][];int x,y;
  56. void resize(int a,int b)
  57. {
  58. x=a;y=b;
  59. memset(d,,sizeof(d));
  60. //d.clear();
  61. //d.resize(x+1);
  62. //for(int i=1;i<=x;i++) d[i].resize(y+1);
  63. }
  64. };
  65. /*
  66. void init_0(M &p)
  67. {
  68. p.resize(p.x,p.y);
  69. }
  70. */
  71. M_NK operator*(const M_NK &a,const M_KK &b)
  72. {
  73. assert(a.y==b.x);
  74. M_NK c;c.resize(a.x,b.y);
  75. int i,j,k;
  76. for(i=;i<=a.x;i++)
  77. for(j=;j<=b.x;j++)
  78. for(k=;k<=b.y;k++)
  79. c.d[i][k]=(c.d[i][k]+ll(a.d[i][j])*b.d[j][k]%md)%md;
  80. return c;
  81. }
  82.  
  83. M_NN operator*(const M_NK &a,const M_KN &b)
  84. {
  85. assert(a.y==b.x);
  86. M_NN c;c.resize(a.x,b.y);
  87. int i,j,k;
  88. for(i=;i<=a.x;i++)
  89. for(j=;j<=b.x;j++)
  90. for(k=;k<=b.y;k++)
  91. c.d[i][k]=(c.d[i][k]+ll(a.d[i][j])*b.d[j][k]%md)%md;
  92. return c;
  93. }
  94. M_KK operator*(const M_KN &a,const M_NK &b)
  95. {
  96. assert(a.y==b.x);
  97. M_KK c;c.resize(a.x,b.y);
  98. int i,j,k;
  99. for(i=;i<=a.x;i++)
  100. for(j=;j<=b.x;j++)
  101. for(k=;k<=b.y;k++)
  102. c.d[i][k]=(c.d[i][k]+ll(a.d[i][j])*b.d[j][k]%md)%md;
  103. return c;
  104. }
  105. M_KK operator*(const M_KK &a,const M_KK &b)
  106. {
  107. assert(a.y==b.x);
  108. M_KK c;c.resize(a.x,b.y);
  109. int i,j,k;
  110. for(i=;i<=a.x;i++)
  111. for(j=;j<=b.x;j++)
  112. for(k=;k<=b.y;k++)
  113. c.d[i][k]=(c.d[i][k]+ll(a.d[i][j])*b.d[j][k]%md)%md;
  114. return c;
  115. }
  116. M_KK o,tt2,t1,t2;
  117. M_NK ou1;M_KN in1;
  118. M_KK p;
  119. int in[][],ou[][];
  120. M_KK poww(const M_KK &a,int b)
  121. {
  122. M_KK ans=o,base=a;
  123. assert(a.x==a.y);
  124. for(;b;base=base*base,b>>=)
  125. if(b&)
  126. ans=ans*base;
  127. return ans;
  128. }
  129.  
  130. int n,K,m;
  131. int solve(int u,int v,int d)
  132. {
  133. if(d==) return u==v;
  134. M_KK tt=t1*poww(t2,d-);
  135. int i,j;
  136. for(i=;i<=K;i++)
  137. {
  138. for(j=;j<=K;j++)
  139. {
  140. tt2.d[i][j]=tt.d[i][j+K];
  141. }
  142. }
  143. M_NK t2=ou1*tt2;int an=u==v;
  144. for(i=;i<=t2.y;i++)
  145. an=(an+ll(t2.d[u][i])*in1.d[i][v]%md)%md;
  146. return an;
  147. }
  148. int main()
  149. {
  150. //freopen("/tmp/3583/6.in","r",stdin);
  151. //freopen("/tmp/3583/6.ans","w",stdout);
  152. int i,j,u,v,d;
  153. scanf("%d%d",&n,&K);
  154. for(i=;i<=n;i++)
  155. {
  156. for(j=;j<=K;j++)
  157. {
  158. scanf("%d",&ou[i][j]);
  159. }
  160. for(j=;j<=K;j++)
  161. {
  162. scanf("%d",&in[i][j]);
  163. }
  164. }
  165. ou1.resize(n,K);
  166. for(i=;i<=n;i++)
  167. {
  168. for(j=;j<=K;j++)
  169. {
  170. ou1.d[i][j]=ou[i][j];
  171. }
  172. }
  173. in1.resize(K,n);
  174. for(i=;i<=K;i++)
  175. {
  176. for(j=;j<=n;j++)
  177. {
  178. in1.d[i][j]=in[j][i];
  179. }
  180. }
  181. p=in1*ou1;
  182. t1.resize(K,*K);
  183. for(i=;i<=K;i++) t1.d[i][i]=t1.d[i][i+K]=;
  184. t2.resize(*K,*K);
  185. for(i=;i<=K;i++)
  186. {
  187. for(j=;j<=K;j++)
  188. {
  189. t2.d[i][j]=t2.d[i][j+K]=p.d[i][j];
  190. }
  191. }
  192. for(i=;i<=K;i++) t2.d[i+K][i+K]=;
  193. tt2.resize(K,K);
  194. o.resize(*K,*K);
  195. for(i=;i<=*K;i++) o.d[i][i]=;
  196. scanf("%d",&m);
  197. while(m--)
  198. {
  199. scanf("%d%d%d",&u,&v,&d);
  200. printf("%d\n",solve(u,v,d));
  201. //return 0;
  202. }
  203. return ;
  204. }

一份有分,可以跑的代码:

  1. #pragma GCC optimize(3)
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<vector>
  6. //#include<cassert>
  7. using namespace std;
  8. #define fi first
  9. #define se second
  10. #define mp make_pair
  11. #define pb push_back
  12. typedef long long ll;
  13. typedef unsigned long long ull;
  14. typedef pair<int,int> pii;
  15. #define vector myvec
  16. template<typename T>
  17. struct myvec
  18. {
  19. T *p;int sz;
  20. myvec():p(),sz(){}
  21. ~myvec(){delete[] p;}
  22. myvec &operator=(const myvec &b)
  23. {
  24. delete[] p;
  25. sz=b.sz;
  26. p=new T[sz];
  27. for(T *i1=p,*i2=b.p;i1!=p+sz;++i1,++i2) *i1=*i2;
  28. return *this;
  29. }
  30. myvec(const myvec &b):p(),sz(){*this=b;}
  31. void resize(int d){sz=d;delete[] p;p=new T[d]();}
  32. T &operator[](int d){return p[d];}
  33. const T &operator[](int d)const{return p[d];}
  34. };
  35. const ll md=;
  36. struct M1
  37. {
  38. vector<vector<ll> > d;int x,y;
  39. M1();
  40. void resize(int xx,int yy)
  41. {
  42. x=xx;y=yy;
  43. d.resize(x+);
  44. for(int i=;i<=x;i++) d[i].resize(y+);
  45. }
  46. };
  47. struct M2
  48. {
  49. M1 d[][];int x,y;
  50. M2();
  51. void resize_sub(int xx,int yy)
  52. {
  53. int i,j;
  54. for(i=;i<=x;i++)
  55. for(j=;j<=y;j++)
  56. d[i][j].resize(xx,yy);
  57. }
  58. };
  59. void init_0(M1 &p)
  60. {
  61. //p.d.clear();
  62. p.resize(p.x,p.y);
  63. }
  64. void init_0(M2 &p)
  65. {
  66. int i,j;
  67. for(i=;i<=;i++)
  68. for(j=;j<=;j++)
  69. init_0(p.d[i][j]);
  70. }
  71. void init_1(M1 &p)
  72. {
  73. init_0(p);//assert(p.x==p.y);
  74. for(int i=;i<=p.x;i++) p.d[i][i]=;
  75. }
  76. void init_1(M2 &p)
  77. {
  78. init_0(p);//assert(p.x==p.y);
  79. for(int i=;i<=p.x;i++) init_1(p.d[i][i]);
  80. }
  81. M1::M1(){x=y=;init_0(*this);}
  82. M2::M2(){x=y=;init_0(*this);}
  83. M1 operator+(const M1 &a,const M1 &b)
  84. {
  85. //assert(a.x==b.x&&a.y==b.y);
  86. M1 c;c.resize(a.x,a.y);
  87. int i,j;
  88. for(i=;i<=a.x;i++)
  89. for(j=;j<=a.y;j++)
  90. c.d[i][j]=(a.d[i][j]+b.d[i][j])%md;
  91. return c;
  92. }
  93. M1 operator*(const M1 &a,const M1 &b)
  94. {
  95. //assert(a.y==b.x);
  96. M1 c;c.resize(a.x,b.y);
  97. int i,j,k;
  98. for(i=;i<=a.x;i++)
  99. for(j=;j<=b.x;j++)
  100. for(k=;k<=b.y;k++)
  101. c.d[i][k]=(c.d[i][k]+a.d[i][j]*b.d[j][k])%md;
  102. return c;
  103. }
  104. M2 operator*(const M2 &a,const M2 &b)
  105. {
  106. //assert(a.y==b.x);
  107. M2 c;c.x=a.x;c.y=b.y;c.resize_sub(a.d[][].x,a.d[][].y);
  108. int i,j,k;
  109. for(i=;i<=a.x;i++)
  110. for(j=;j<=b.x;j++)
  111. for(k=;k<=b.y;k++)
  112. c.d[i][k]=(c.d[i][k]+a.d[i][j]*b.d[j][k]);
  113. return c;
  114. }
  115. M1 ou1,in1,p;
  116. int ou[][],in[][];
  117. M2 poww(const M2 &a,ll b)
  118. {
  119. //printf("tt%d %d\n",a.x,a.y);
  120. M2 ans,base=a;/*assert(a.x==a.y);*/ans.x=ans.y=a.x;
  121. ans.resize_sub(a.d[][].x,a.d[][].y);init_1(ans);
  122. for(;b;base=base*base,b>>=)
  123. if(b&)
  124. ans=ans*base;
  125. return ans;
  126. }
  127. int n,K,m;
  128.  
  129. /*
  130. void out(const M1 &a)
  131. {
  132. puts("start");
  133. int i,j;
  134. for(i=1;i<=a.x;i++)
  135. {
  136. for(j=1;j<=a.y;j++)
  137. {
  138. printf("%lld ",a.d[i][j]);
  139. }
  140. puts("");
  141. }
  142. puts("end");
  143. fflush(stdout);
  144. }
  145.  
  146. void out(const M2 &p)
  147. {
  148. puts("st");
  149. printf("xy%d %d\n",p.x,p.y);
  150. for(int i=1;i<=p.x;i++)
  151. for(int j=1;j<=p.y;j++)
  152. out(p.d[i][j]),puts("");
  153. puts("ed");
  154. }
  155. */
  156. M2 t1,t2;
  157. int solve(int u,int v,int d)
  158. {
  159. if(d==) return u==v;
  160. return ((u==v)+(ou1*((t1*poww(t2,d-)).d[][])*in1).d[u][v])%md;
  161. }
  162. int main()
  163. {
  164. int i,j,u,v,d;
  165. scanf("%d%d",&n,&K);
  166. for(i=;i<=n;i++)
  167. {
  168. for(j=;j<=K;j++)
  169. {
  170. scanf("%d",&ou[i][j]);
  171. }
  172. for(j=;j<=K;j++)
  173. {
  174. scanf("%d",&in[i][j]);
  175. }
  176. }
  177. ou1.resize(n,K);
  178. for(i=;i<=n;i++)
  179. {
  180. for(j=;j<=K;j++)
  181. {
  182. ou1.d[i][j]=ou[i][j];
  183. }
  184. }
  185. in1.resize(K,n);
  186. for(i=;i<=K;i++)
  187. {
  188. for(j=;j<=n;j++)
  189. {
  190. in1.d[i][j]=in[j][i];
  191. }
  192. }
  193. p=in1*ou1;
  194. t1.x=;t1.y=;t1.resize_sub(K,K);
  195. //t1.d[1][1]=M1(1,K,K);
  196. init_1(t1.d[][]);init_1(t1.d[][]);
  197. t2.x=t2.y=;t2.resize_sub(K,K);
  198. t2.d[][]=t2.d[][]=p;
  199. //t2.d[2][2]=M1(1,K,K);
  200. init_1(t2.d[][]);
  201. //out((t1*poww(t2,0)).d[1][2]);
  202. scanf("%d",&m);
  203. while(m--)
  204. {
  205. scanf("%d%d%d",&u,&v,&d);
  206. printf("%d\n",solve(u,v,d));
  207. }
  208. return ;
  209. }

bzoj3583 杰杰的女性朋友 || bzoj4362 Graph的更多相关文章

  1. bzoj3583: 杰杰的女性朋友 && 4362: Graph

    Description 给出一张n个点的有向图G(V,E).对于任意两个点u,v(u可以等于v),u向v的连边数为: ∑OUT(u,i) * IN(v,i),其中1<=i<=K 其中k和数 ...

  2. [BZOJ3583]杰杰的女性朋友(矩阵快速幂)

    杰杰的女性朋友 时间限制:10s      空间限制:256MB 题目描述 杰杰是魔法界的一名传奇人物.他对魔法具有深刻的洞察力,惊人的领悟力,以及令人叹为观止的创造力.自从他从事魔法竞赛以来,短短几 ...

  3. BZOJ3583 杰杰的女性朋友 矩阵

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ3583.html 题目传送门 - BZOJ3583 题意 有一个 $n$ 个点构成的有向图. 对于每一个 ...

  4. BZOJ3583 : 杰杰的女性朋友

    将$I$转置,设$G=OI$,则$ans=G^0+G^1+...+G^d$. 注意到$G^d=O(IO)^{d-1}I$,而$IO$是大小为$k\times k$的矩阵,可以通过倍增在$O(k^3\l ...

  5. 复旦大学EWP菁英女性课程(复旦卓越女性课程改版后第一期) _复旦大学、女性课程、高级研修班、心理学、EWP_培训通课程

    复旦大学EWP菁英女性课程(复旦卓越女性课程改版后第一期) _复旦大学.女性课程.高级研修班.心理学.EWP_培训通课程 复旦大学EWP菁英女性课程(复旦卓越女性课程改版后第一期)    学      ...

  6. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  7. cojs QAQ的矩阵 题解报告

    题目描述非常的清晰 首先我们考虑(A*B)^m的求法,这个部分可以参考BZOJ 杰杰的女性朋友 我们不难发现(A*B)^m=A*(B*A)^(m-1)*B A*B是n*n的矩阵,而B*A是k*k的矩阵 ...

  8. qbxt五一数学Day1

    目录 I. 基础知识 1. 带余除法(小学) 1. 定义 2. 性质 2. 最大公约数(gcd)/ 最小公倍数(lcm) 1. 定义 2. 性质 3. 高精度 II. 矩阵及其应用 1. 定义 2. ...

  9. DOM实战

    作者声明:本博客中所写的文章,都是博主自学过程的笔记,参考了很多的学习资料,学习资料和笔记会注明出处,所有的内容都以交流学习为主.有不正确的地方,欢迎批评指正 视频来源:https://www.bil ...

随机推荐

  1. MSP430G2553需要注意的一些参数

    转载请注明出处:http://www.cnblogs.com/connorzx/p/3632952.html 把一些具体芯片信息列出来,以便于查看. 1.时钟 (1)MCLK,Master Clock ...

  2. 继续servlet理论篇

    唉,毕业是件很麻烦的事情,实习也是一件很郁闷的事情,现在公司很注重基础,所以 所以还要看java,不过,我年轻,我有激情.来吧,来着不惧,说这话,有些心虚. HttpServlet类中所提供的doGe ...

  3. hdu 1280 前m大的数(排序)

    题意:排序 思路:排序 #include<iostream> #include<stdio.h> #include<algorithm> using namespa ...

  4. observer远程监控服务器

    因为需要监控服务器的状况,所以要使用工具observer.但是observer是采用wxWidget开发的,远程机器没有此环境.于是在windows机器上装了虚拟机ubuntu,又折腾erlang和w ...

  5. hdu-5776 sum(同余)

    题目链接: sum Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 131072/131072 K (Java/Others) Pro ...

  6. Linux-用户和权限

    1 Linux所有内容都是文件 归一的思想 面向对象的思想 文件只需要做增删改查的操作 2 延迟读取 一般的文本读取工具都是先将内容全部都读入内存中 cat的机制不同 是读一行显示一行 这与它的功能有 ...

  7. CodeForces - 597C:Subsequences (主席树+DP)

    For the given sequence with n different elements find the number of increasing subsequences with k + ...

  8. cuda 版本查阅

    查看cuda版本 cat  /usr/local/cuda/version.txt nvcc -V

  9. 关于yolov3 训练输出值

    Region xx: cfg文件中yolo-layer的索引: Avg IOU:当前迭代中,预测的box与标注的box的平均交并比,越大越好,期望数值为1: Class: 标注物体的分类准确率,越大越 ...

  10. C++之static类成员,static类成员函数

    0.static修饰类中成员,表示类的共享数据 1.static类成员 在C++primer里面说过,static类成员不像普通的类数据成员,static类数据成员独立于一切类对象处在.static类 ...