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;
}
时间: 2024-10-27 06:42:53

HDU - 2254 奥运 (求等比数列和)的相关文章

HDU 2254 奥运(矩阵快速幂+二分等比序列求和)

HDU 2254 奥运(矩阵快速幂+二分等比序列求和) ACM 题目地址:HDU 2254 奥运 题意: 中问题不解释. 分析: 根据floyd的算法,矩阵的k次方表示这个矩阵走了k步. 所以k天后就算矩阵的k次方. 这样就变成:初始矩阵的^[t1,t2]这个区间内的v[v1][v2]的和. 所以就是二分等比序列求和上场的时候了. 跟HDU 1588 Gauss Fibonacci的算法一样. 代码: /* * Author: illuz <iilluzen[at]gmail.com> * B

HDU 2254 奥运(矩阵)

题目地址:HDU 2254 必须得吐槽一下..这题的数据是又弱又坑..样例不过都能AC..还有..居然还有重边..WA了一晚上.. 吐槽完毕,言归正传.. 根据离散数学里面的可达矩阵的性质,我们知道一个有向图的邻接矩阵的前n次幂的和即为可达矩阵,那么要求[t1-t2]之内的路径的条数,因为题目说了t1 = 0的时候为0.那么假设邻接矩阵为A,那么要求的就是A^(t1-1)+A^(t1)+...+A^(t2-1),为什么是从t1-1开始呢,因为邻接矩阵本身代表走一步的结果. 然后再加上离散化就可以

HDU 2254 - 奥运

先离散化,然后套等比数列二分求和 二分的离散化会有问题,没出现过的数字可能定位在数组中部,就是和已出现过的数字占用同一编号,故可以先判断数字有无出现过 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <map> 6 using namespace std; 7 #define LL long long

HDU 2254 奥运(数论+矩阵)

题目中文的不解释啊. .. 须要注意的就是:离散数学中,有向图的邻接矩阵A表示全部点之间路径长度为1的路径数量,A^n则表示路径长度为n的路径数量.故须要求某两点在(A^t1)~(A^t2)的路径数量之和. 奥运 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2251    Accepted Submission(s): 572 Pr

HDU - 1588 Gauss Fibonacci (矩阵快速幂+二分求等比数列和)

Description Without expecting, Angel replied quickly.She says: "I'v heard that you'r a very clever boy. So if you wanna me be your GF, you should solve the problem called GF~. " How good an opportunity that Gardon can not give up! The "Prob

HDU 4911 Inversion 求逆序数对

点击打开链接 Inversion Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 1106    Accepted Submission(s): 474 Problem Description bobo has a sequence a1,a2,-,an. He is allowed to swap two adjacent num

poj 1226 hdu 1238 Substrings 求若干字符串正串及反串的最长公共子串 2002亚洲赛天津预选题

题目:http://poj.org/problem?id=1226 http://acm.hdu.edu.cn/showproblem.php?pid=1238 其实用hash+lcp可能也可以,甚至可能写起来更快,不过我没试,我最近在练习后缀数组,所以来练手 后缀数组的典型用法之一----------------后缀数组+lcp+二分 思路:1.首先将所有的字符串每读取一个,就将其反转,作为一组,假设其下标为i到j,那么cnt[i]到cnt[j]都标记为一个数字(这个数字意思是第几个读入的字符

hdu 4192(表达式求值)

题意:给一个表达式当中有一些变量,然后告诉你一些数字你可以任意排列,问能不能求出要求的结果. 思路:由于变量数目较小所以直接全排列枚举即可,然后用栈处理表达式. 代码如下: 1 /************************************************** 2 * Author : xiaohao Z 3 * Blog : http://www.cnblogs.com/shu-xiaohao/ 4 * Last modified : 2014-06-28 21:50 5

hdu 2242 无向图/求用桥一分为二后使俩个bcc点权值和之差最小并输出 /缩点+2次新图dfs

题意如标题所述, 先无向图缩点,统计出每个bcc权,建新图,然后一遍dfs生成树,标记出每个点(新图)以及其子孙的权值之和.这样之后就可以dfs2来枚举边(原图的桥),更新最小即可. 调试了半天!原来是建老图时候链式前向星和新图的vector<vector< int>>俩种存图搞乱了!!!不可原谅!哎!愚蠢!愚不可及!提交后1A. 后来百度之后,发现说是用树形dp,看了代码解法,竟然和我的是一样的算法..原来这种算法可以叫树形dp...的确有点dp味道..不过感觉不太浓.. 以后多