HDU 2254 奥运(矩阵+二分等比求和)

奥运

【题目链接】奥运

【题目类型】矩阵+二分等比求和

&题解:

首先离散化城市,之后就是矩阵快速幂了,但让求的是A(t1)+A(t1+1)+...+A^(t2),我先想的是打表,但时间真的太慢了,之后网上查的二分等比求和,这样logn就可以求等比矩阵的前n项和了
还有用二分等比求和时,矩阵最好用数组表示,尽量不用vector,我试了好几发,总是T,当然也有可能是我写的low了吧 - -

&代码:

#include <cstdio>
#include <bitset>
#include <iostream>
#include <set>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
using namespace std;
#define INF 0x3f3f3f3f
typedef long long ll;
const int N= 30 +9;

struct Matrix
{
	int m[N][N];
};
Matrix I,ZZ;
int n,m,M=2008;

Matrix add(Matrix a,Matrix b)
{
	Matrix c;
	for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
			c.m[i][j]=(a.m[i][j]+b.m[i][j])%M;
	return c;
}

Matrix multi(Matrix a,Matrix b)
{
	Matrix c;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			c.m[i][j]=0;
			for(int k=0;k<n;k++)
				c.m[i][j]=(c.m[i][j]+a.m[i][k]*b.m[k][j])%M;
		}
	}
	return c;
}
Matrix power(Matrix A,ll n)
{
	Matrix ans=I;
	while(n){
		if(n&1)
			ans=multi(ans,A);
		A=multi(A,A);
		n>>=1;
	}
	return ans;
}

Matrix sum(Matrix A,ll k)
{
	if(k<=0) return ZZ;
	if(k==1) return A;
//	cout<<"k="<<k<<endl;
	Matrix t=sum(A,k/2);
	Matrix cur=power(A,k/2+(k&1));
	t=add(t,multi(t,cur));
	if(k&1) t=add(t,cur);
	return t;
}
int v1,v2,t1,t2;
map<int,int> tb;
int main()
{
	freopen("E:1.txt","r",stdin);
	while(cin>>n){
		Matrix gra;
		//一定记得要初始化啊 矩阵I ZZ 和gra 
		tb.clear();
		for(int i=0;i<35;i++){
			I.m[i][i]=1;
			for(int j=0;j<35;j++){
				ZZ.m[i][j]=0;
				gra.m[i][j]=0;
			}
		}
		int ct=0;
		for(int i=0;i<n;i++){
			int u,v;
			cin>>u>>v;
			if(tb[u]==0)
				tb[u]=++ct;
			if(tb[v]==0)
				tb[v]=++ct;
			gra.m[tb[u]-1][tb[v]-1]++;
			gra.m[tb[u]-1][tb[v]-1]%=M;
		}
		cin>>m;
		for(int i=0;i<m;i++){
			cin>>v1>>v2>>t1>>t2;

			if(!tb[v1]||!tb[v2]){
				puts("0");
			}
			else{
				Matrix an1=sum(gra,t2);
				Matrix an2=sum(gra,t1-1);
				//这块 处理的时候减1了 输入地图的时候也要减1啊
				cout<<((an1.m[tb[v1]-1][tb[v2]-1]-an2.m[tb[v1]-1][tb[v2]-1])%M+M)%M<<endl;
			}
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/s1124yy/p/6655611.html