bzoj3583 杰杰的女性朋友

题目链接

本来是求点a到点b的路径

由于是完全图且K固定,就可以当成是每个原图点往k个中转点连了in[i][kj]条边,每个中转点往每个原图点连了out[kj][i]条边

于是我们就可以把中转点和原图点反一下

求两个原图点的路径就变成了求两个中转点的路径

用矩乘快速幂就可以了

如图ki,kj为中转点

如图如果从1到4沿着黑色边走的话,就可以当做是  ki到kj的方案数   x  1到ki的方案数   x   kj到4的方案数

复杂度:O(k^3)

矩乘:O(k^3*log2(d-1))很优秀啊……

  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstdlib>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<string>
  7 #include<cmath>
  8 #include<ctime>
  9 #include<queue>
 10 #include<stack>
 11 #include<map>
 12 #include<set>
 13 #define rre(i,r,l) for(int i=(r);i>=(l);i--)
 14 #define re(i,l,r) for(int i=(l);i<=(r);i++)
 15 #define Clear(a,b) memset(a,b,sizeof(a))
 16 #define inout(x) printf("%d",(x))
 17 #define douin(x) scanf("%lf",&x)
 18 #define strin(x) scanf("%s",(x))
 19 #define LLin(x) scanf("%lld",&x)
 20 #define op operator
 21 #define CSC main
 22 typedef unsigned long long ULL;
 23 typedef const int cint;
 24 typedef long long LL;
 25 using namespace std;
 26 void inin(int &ret)
 27 {
 28     ret=0;int f=0;char ch=getchar();
 29     while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
 30     while(ch>='0'&&ch<='9')ret*=10,ret+=ch-'0',ch=getchar();
 31     ret=f?-ret:ret;
 32 }
 33 int out[2010][22],in[22][2010],ans;
 34 cint mod=1e9+7;
 35 int n,m,l[22];
 36 struct Mat
 37 {
 38     LL a[25][25];
 39     void in(int x)
 40     {
 41         re(i,1,m)re(j,1,m)a[i][j]=(i==j)*x;
 42     }
 43     LL* op [] (int x){return x[a];}
 44     Mat op + (Mat rhs)
 45     {
 46         Mat ret;ret.in(0);
 47         re(i,1,m)re(j,1,m)ret[i][j]=(a[i][j]+rhs[i][j]%mod)%mod;
 48         return ret;
 49     }
 50     Mat op * (Mat rhs)
 51     {
 52         Mat ret;ret.in(0);
 53         re(i,1,m)re(j,1,m)re(k,1,m)
 54             ret[i][k]=(ret[i][k]+1LL*a[i][j]*rhs[j][k])%mod;
 55         return ret;
 56     }
 57 }ii,hh;
 58 Mat ret,shu;
 59 void solve(int x)
 60 {
 61     if(x<0)return ret=hh,void();
 62     Mat a=shu,b=a,v=ii,s=ii;
 63     ret.in(0);
 64     while(x)
 65     {
 66         if(x&1)s=s+(b*v),v=v*a;
 67         x>>=1;
 68         Mat k=a+ii;
 69         b=b*k;
 70         a=a*a;
 71     }
 72     ret=s;
 73 }
 74 int CSC()
 75 {
 76     inin(n),inin(m);
 77     ii.in(1);
 78     re(i,1,n)
 79     {
 80         re(j,1,m)inin(out[i][j]);
 81         re(j,1,m)inin(in[j][i]);
 82     }
 83     shu.in(0);hh.in(0);
 84     re(i,1,m)re(j,1,n)re(k,1,m)
 85         shu[i][k]=(shu[i][k]+1LL*in[i][j]*out[j][k])%mod;
 86     int q;
 87     inin(q);
 88     while(q--)
 89     {
 90         int a,b,d;
 91         inin(a),inin(b),inin(d);
 92         solve(d-1);
 93         re(i,1,m)l[i]=0;
 94         re(i,1,m)re(j,1,m)l[j]=(l[j]+1LL*out[a][i]*ret[i][j]%mod)%mod;
 95         ans=0;
 96         re(i,1,m)ans=(ans+1LL*l[i]*in[i][b])%mod;
 97         printf("%d\n",ans+(a==b));
 98     }
 99     return 0;
100 }

 

posted @ 2016-02-25 14:01  HugeGun  阅读(378)  评论(0编辑  收藏  举报