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

Problem 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
</pre><pre style="font-family: 'Courier New'; background-color: rgb(244, 251, 255);"><pre name="code" class="cpp">#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-10
///#define M 1000100
#define LL __int64
///#define LL long long
///#define INF 0x7ffffff
#define INF 0x3f3f3f3f
#define PI 3.1415926535898
#define zero(x) ((fabs(x)<eps)?

0:x)

#define mod 2008

const int maxn = 210;

using namespace std;

struct matrix
{
    int f[31][31];
};
matrix p[10001];
map<int, int>mp;

matrix mul(matrix a, matrix b, int n)
{
    matrix c;
    memset(c.f, 0, sizeof(c.f));
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            for(int k = 0; k < n; k++) c.f[i][j] += a.f[i][k]*b.f[k][j];
            c.f[i][j] %= mod;
        }
    }
    return c;
}

matrix pow_mod(matrix a, int b, int n)
{
    matrix s;
    memset(s.f, 0 , sizeof(s.f));
    for(int i = 0; i < n; i++) s.f[i][i] = 1;
    while(b)
    {
        if(b&1) s = mul(s, a, n);
        a = mul(a, a, n);
        b >>= 1;
    }
    return s;
}

matrix Add(matrix a,matrix b, int n)
{
    matrix c;
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            c.f[i][j] = a.f[i][j]+b.f[i][j];
            c.f[i][j] %= mod;
        }
    }
    return c;
}

int main()
{
    int n, m;
    while(scanf("%d",&n)!=EOF)
    {
        int u, v;
        int ans = 0;
        mp.clear();
        memset(p[0].f, 0, sizeof(p[0].f));
        for(int i = 0; i < n; i++)
        {
            scanf("%d %d",&u, &v);
            if(mp.find(u) == mp.end()) mp[u] = ans++;
            if(mp.find(v) == mp.end()) mp[v] = ans++;
            p[0].f[mp[u]][mp[v]] ++;
        }

        for(int i = 1; i < 10001; i++) p[i] = mul(p[i-1], p[0], ans);
        scanf("%d",&m);
        int t1, t2, v1, v2;
        while(m--)
        {
            scanf("%d %d %d %d",&v1, &v2, &t1, &t2);
            if(t1 > t2) swap(t1,t2);
            if(mp.find(v1) == mp.end() || mp.find(v2) == mp.end() || t1 == 0 && t2 == 0)
            {
                puts("0");
                continue;
            }
            int sum = 0;

            for(int i = t1-1; i < t2; i++)
            {
                if(i == -1) continue;
                sum += p[i].f[mp[v1]][mp[v2]]%mod;
            }
            printf("%d\n",sum%mod);
            ///cout<<(sum%mod)<<endl;
        }
    }
    return 0;
}
				
时间: 2024-10-24 17:56:19

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 奥运 (求等比数列和)

Description 北京迎来了第一个奥运会,我们的欢呼声响彻中国大地,所以今年的奥运金牌 day day up! 比尔盖兹坐上鸟巢里,手里摇着小纸扇,看的不亦乐乎,被俺们健儿的顽强拼搏的精神深深的感动了.反正我的钱也多的没地方放了,他对自己说,我自己也来举办一个奥运会.看谁的更火.只是他的奥运会非常特别: 1 參加人员必须是中国人: 2 至少会加法运算(由于要计算本人获得的金牌数) 他知道中国有非常多的名胜古迹,他知道自己在t1 到 t2天内不可能把全部的地方都玩遍,所以他决定指定两个地方v

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 4887 Endless Punishment (矩阵离散对数)

题意: 给你两个长度为n(n <= 31)的01序列A, B,问A序列最少改变多少次能变成B序列.序列的一次改变是这样的,首先有两个集合S1.S2,每个集合中表示的都是下标,如果集合S1中1的个数是奇数个,那么把序列的第一个数去掉,然后在尾部加上一个数1,偶数个的话则是加上一个数0,然后将S2集合对应的位置异或一下,这就是改变了一次. 思路:由于n<=31,即可知总的不同序列个数是2^n.对于一个序列的一次改变,可以构造个转移矩阵,那么改变一次其实就是乘一次这个矩阵,设初始矩阵是A, 转移矩阵

HDU 4920 Matrix multiplication(矩阵相乘)

各种TEL,233啊.没想到是处理掉0的情况就可以过啊.一直以为会有极端数据.没想到竟然是这样的啊..在网上看到了一个AC的神奇的代码,经典的矩阵乘法,只不过把最内层的枚举,移到外面就过了啊...有点不理解啊,复杂度不是一样的吗.. Matrix multiplication Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 640 

HDU 2604 Queuing (矩阵快速幂)

HDU 2604 Queuing (矩阵快速幂) ACM 题目地址:HDU 2604 Queuing 题意: n个人排队,f表示女,m表示男,包含子串'fmf'和'fff'的序列为O队列,否则为E队列,有多少个序列为E队列. 分析: 矩阵快速幂入门题. 下面引用巨巨解释: 用f(n)表示n个人满足条件的结果,那么如果最后一个人是m的话,那么前n-1个满足条件即可,就是f(n-1): 如果最后一个是f那么这个还无法推出结果,那么往前再考虑一位:那么后三位可能是:mmf, fmf, mff, fff

hdu 4196(数论)

题意:问小于n的数的乘积能拼成的最大平方数是多少? 思路:给n!做质数分解在除去指数为奇数的那些质数,由于题目中需要模运算所以不能直接除,必须乘上摸逆. 代码如下: 1 /************************************************** 2 * Author : xiaohao Z 3 * Blog : http://www.cnblogs.com/shu-xiaohao/ 4 * Last modified : 2014-06-28 15:26 5 * Fi

hdu 4920 Matrix multiplication(矩阵坑题)

http://acm.hdu.edu.cn/showproblem.php?pid=4920 被这道题虐了一下午,啥也不说了.继续矩阵吧. 超时就超在每步取余上,要放在最后取余,再者注意三个循环的次序. #include <stdio.h> #include <map> #include <set> #include <stack> #include <queue> #include <vector> #include <cma