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;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值