矩阵快速幂之奥运 hdu 2254

Posted hgangang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了矩阵快速幂之奥运 hdu 2254相关的知识,希望对你有一定的参考价值。

1、城市的编号不是从0到n-1,而是随便的一个数字,需要离散化否则不能存相关信息

2、城市数不超过30,也就是说我的方法开矩阵不超过60,但是我残念的一开始以为最多可能有20000个不同城市    血崩!

3、图中可能有重边,所以别用=1,要用++操作

4、询问中v1,v2可能在前面的城市编号集中没有出现,那么此时答案为0

5、t1可能比t2大,这种情况你就交换下t1,t2

好了接下来讲下解法:

由离散知识我们知道:

,矩阵A的n次方里面的(A^n)[i][j]表示从i到j且路径长度为n的不同路径条数。这一定理正好适用这一题目。我用邻接矩阵来建图(单向边,一条边对应一个++操作)得到矩阵A,题目要求的就是{A^(t1)}[v1][v2]+{A^(t1+1)}[v1][v2]+{A^(t1+2)}[v1][v2]+......+{A^(t2)}

然后就是矩阵乘法模板优化一下

#include<bits/stdc++.h>

using namespace std;
const int mod=2008;
int n,sum;
struct node

int a[35][35];
mt,MT[20005];
int num[20005];
struct st

int l,r;
f[20005];
//node mat(node x,node y)
//
// node c;
// for(int i=0;i<n;i++)
// for(int j=0;j<n;j++)
// c.a[i][j]=0;
// for(int i=0;i<n;i++)
// for(int j=0;j<n;j++)
// for(int k=0;k<n;k++)
//
// c.a[i][j]=(c.a[i][j]+x.a[i][k]*y.a[k][j]);
// if(c.a[i][j]>=2008)
// c.a[i][j]%=2008;
//
// return c;
//
struct node mat(node cur,node now)

node ww;
memset(ww.a,0,sizeof(ww.a));
int i,j,k;
for(i=1;i<=n;i++)
for(k=1;k<=n;k++)
if(cur.a[i][k])

for(j=1;j<=n;j++)
if(now.a[k][j])

ww.a[i][j]=ww.a[i][j]+(cur.a[i][k]*now.a[k][j])%2008;
if(ww.a[i][j]>=2008)
ww.a[i][j]%=2008;


return ww;

//int EF(int numb)
//
// int l=1;
// int r=sum;
// int ans=0;
// while(l<=r)
// int mid=(l+r)/2;
// if(num[mid]>numb) r=mid-1;
// else
// l=mid+1,ans=mid;
//
// return ans;
//
int EF(int numm)//二分查找

int l=1;
int r=sum;
int mid=(l+r)/2;
while(l<r)

if(num[mid]>numm)
r=mid-1;
else if(num[mid]<numm)
l=mid+1;
else return mid;
mid=(l+r)/2;

return mid;

void solve()

int m,v1,v2,t1,t2,ans;
scanf("%d",&m);
while(m--)
ans=0;
scanf("%d%d%d%d",&v1,&v2,&t1,&t2);
if(t1>t2) swap(t1,t2);
int l=EF(v1);
int r=EF(v2);
if(v1!=num[l]||v2!=num[r])
puts("0");
continue;

for(int i=t1;i<=t2;i++)
ans=(ans+MT[i].a[l][r]);
if(ans>=2008)
ans%=mod;

printf("%d\n",ans);


int main()

int len;
while(scanf("%d",&n)>0)
len=0;
for(int i=1;i<=n;i++)
scanf("%d %d",&f[i].l,&f[i].r);
num[++len]=f[i].l;
num[++len]=f[i].r;

memset(mt.a,0,sizeof(mt.a));
sort(num+1,num+len+1);
sum=unique(num+1,num+1+len)-(num+1);
for(int i=1;i<=n;i++)
int l=EF(f[i].l);
int r=EF(f[i].r);
// printf("%d %d\n",l,r);
mt.a[l][r]++;

MT[1]=mt;
for(int i=2;i<=10000;i++)
MT[i]=mat(mt,MT[i-1]);

solve();

return 0;

以上是关于矩阵快速幂之奥运 hdu 2254的主要内容,如果未能解决你的问题,请参考以下文章

HDU 2254 奥运(数论+矩阵)

*HDU2254 矩阵乘法

一些特殊的矩阵快速幂 hdu5950 hdu3369 hdu 3483

求幂大法,矩阵快速幂,快速幂模板题--hdu4549

HDU 5690 矩阵快速幂

矩阵快速幂计算hdu1575