HDU - 2254 奥运 (求等比数列和)

Description

北京迎来了第一个奥运会,我们的欢呼声响彻中国大地,所以今年的奥运金牌 day day up!
比尔盖兹坐上鸟巢里,手里摇着小纸扇,看的不亦乐乎,被俺们健儿的顽强拼搏的精神深深的感动了。反正我的钱也多的没地方放了,他对自己说,我自己也来举办一个奥运会,看谁的更火。不过他的奥运会很特别:
1 参加人员必须是中国人;
2 至少会加法运算(因为要计算本人获得的金牌数)
他知道中国有很多的名胜古迹,他知道自己在t1 到 t2天内不可能把所有的地方都玩遍,所以他决定指定两个地方v1,v2,如果参赛员能计算出在t1到t2天(包括t1,t2)内从v1到v2共有多少种走法(每条道路走需要花一天的时间,且不能在某个城市停留,且t1=0时的走法数为0),那么他就会获得相应数量的金牌,城市的总数<=30,两个城市间可以有多条道路
,每条都视为是不同的。
 

Input

本题多个case,每个case:
输入一个数字n表示有n条道路 0<n<10000
接下来n行每行读入两个数字 p1,p2 表示城市p1到p2有道路,并不表示p2到p1有道路 (0<=p1,p2<2^32)
输入一个数字k表示有k个参赛人员
接下来k行,每行读入四个数据v1,v2,t1,t2 (0<=t1,t2<10000)
 

Output

对于每组数据中的每个参赛人员输出一个整数表示他获得的金牌数(mod 2008)
 

Sample Input

    
    
6 1 2 1 3 2 3 3 2 3 1 2 1 3 1 2 0 0 1 2 1 100 4 8 3 50
 

Sample Output

  
  
0 1506 0

思路:矩阵的基本应用之一:我们都知道s[a][b]可以代表一步从a到b的路径数,那么矩阵的n次方就代表走n步的路径数。又偷了个模板

#include <map>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=35;
const int mod=2008;

class Matrix {
	public:
		int a[maxn][maxn];
		int n;  

		void init(int x) {
			memset(a,0,sizeof(a));
			if (x)  
				for (int i = 0; i < maxn ; i++)
					a[i][i] = 1;
		}

		Matrix operator +(Matrix b) {
			Matrix c;
			c.n = n;
			for (int i = 0; i < n; i++)
				for (int j = 0; j < n; j++)
					c.a[i][j] = (a[i][j] + b.a[i][j]) % mod;
			return c;
		}

		Matrix operator +(int x) {
			Matrix c = *this;
			for (int i = 0; i < n; i++)
				c.a[i][i] += x;
			return c;
		}

		Matrix operator *(Matrix b)
		{
			Matrix p;
			p.n = b.n;   
			p.init(0);
			for (int i = 0; i < n; i++)
				for (int j = 0; j < n; j++)
				for (int k = 0; k < n; k++)
					p.a[i][j] = (p.a[i][j] + (a[i][k]*b.a[k][j])%mod) % mod;
			return p;
		}

		Matrix power(int t) {
			Matrix ans,p = *this;
			ans.n = p.n;  
			ans.init(1);
			while (t) {
				if (t & 1)
					ans=ans*p;
				p = p*p;
				t >>= 1;
			}
			return ans;
		}
}a;
map<int,int> mp;

 //分治求(a^1+a^2+...+.a^n)%mod
Matrix Cal(Matrix a,int n)  {
	if (n == 1)
		return a;
	if (n & 1)
		return a.power(n) + Cal(a, n-1);
	else
		return Cal(a, n/2) * (a.power(n/2) + 1);
}

int main() {
	int n,m;
	while (scanf("%d",&n) != EOF) {
		a.init (0);
		mp.clear();
		int id = 0, u, v, t1, t2;
		for (int i = 0; i < n; i++) {
			scanf("%d%d",&u,&v);
			if (mp.find(u) == mp.end())
				mp[u]=id++;
			if (mp.find(v) == mp.end())
				mp[v]=id++;
			a.a[mp[u]][mp[v]]++;
		}
		a.n = id;   
		scanf("%d",&m);
		while (m--) {
			scanf("%d%d%d%d",&u,&v,&t1,&t2);
			if (mp.find(u)==mp.end() || mp.find(v)==mp.end()) {
				printf("0\n");
				continue;
			}
			if (t1 > t2) 
				swap(t1,t2);
			int s = mp[u],t = mp[v];
			if (t1 == 0) {
				if (t2 == 0) 
					printf("0\n");
				else 
					printf("%d\n",Cal(a,t2).a[s][t]);
			}
			else if (t1 == 1) {
				printf("%d\n",Cal(a,t2).a[s][t]);
			}
			else {
				int ans = Cal(a,t2).a[s][t]-Cal(a,t1-1).a[s][t];
				ans = (ans%mod + mod)%mod;
				printf("%d\n",ans);
			}
		}
	}
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值