zoukankan      html  css  js  c++  java
  • 【矩阵快速幂】之奥运 hdu 2254

    1、城市的编号不是从0到n-1,而是随便的一个数字,需要离散化否则不能存相关信息

    2、城市数不超过30,也就是说我的方法开矩阵不超过60,但是我残念的一开始以为最多可能有20000个不同城市    血崩!

    3、图中可能有重边,所以别用=1,要用++操作

    4、询问中v1,v2可能在前面的城市编号集中没有出现,那么此时答案为0

    5、t1可能比t2大,这种情况你就交换下t1,t2

    好了接下来讲下解法:

    由离散知识我们知道:

    ,矩阵A的n次方里面的(A^n)[i][j]表示从i到j且路径长度为n的不同路径条数。这一定理正好适用这一题目。我用邻接矩阵来建图(单向边,一条边对应一个++操作)得到矩阵A,题目要求的就是{A^(t1)}[v1][v2]+{A^(t1+1)}[v1][v2]+{A^(t1+2)}[v1][v2]+......+{A^(t2)}

    然后就是矩阵乘法模板优化一下

    #include<bits/stdc++.h>

    using namespace std;
    const int mod=2008;
    int n,sum;
    struct node
    {
    int a[35][35];
    }mt,MT[20005];
    int num[20005];
    struct st
    {
    int l,r;
    }f[20005];
    //node mat(node x,node y)
    //{
    // node c;
    // for(int i=0;i<n;i++)
    // for(int j=0;j<n;j++)
    // c.a[i][j]=0;
    // for(int i=0;i<n;i++)
    // for(int j=0;j<n;j++)
    // for(int k=0;k<n;k++)
    // {
    // c.a[i][j]=(c.a[i][j]+x.a[i][k]*y.a[k][j]);
    // if(c.a[i][j]>=2008)
    // c.a[i][j]%=2008;
    // }
    // return c;
    //}
    struct node mat(node cur,node now)
    {
    node ww;
    memset(ww.a,0,sizeof(ww.a));
    int i,j,k;
    for(i=1;i<=n;i++)
    for(k=1;k<=n;k++)
    if(cur.a[i][k])
    {
    for(j=1;j<=n;j++)
    if(now.a[k][j])
    {
    ww.a[i][j]=ww.a[i][j]+(cur.a[i][k]*now.a[k][j])%2008;
    if(ww.a[i][j]>=2008)
    ww.a[i][j]%=2008;
    }
    }
    return ww;
    }
    //int EF(int numb)
    //{
    // int l=1;
    // int r=sum;
    // int ans=0;
    // while(l<=r){
    // int mid=(l+r)/2;
    // if(num[mid]>numb) r=mid-1;
    // else
    // l=mid+1,ans=mid;
    // }
    // return ans;
    //}
    int EF(int numm)//二分查找
    {
    int l=1;
    int r=sum;
    int mid=(l+r)/2;
    while(l<r)
    {
    if(num[mid]>numm)
    r=mid-1;
    else if(num[mid]<numm)
    l=mid+1;
    else return mid;
    mid=(l+r)/2;
    }
    return mid;
    }
    void solve()
    {
    int m,v1,v2,t1,t2,ans;
    scanf("%d",&m);
    while(m--){
    ans=0;
    scanf("%d%d%d%d",&v1,&v2,&t1,&t2);
    if(t1>t2) swap(t1,t2);
    int l=EF(v1);
    int r=EF(v2);
    if(v1!=num[l]||v2!=num[r]){
    puts("0");
    continue;
    }
    for(int i=t1;i<=t2;i++){
    ans=(ans+MT[i].a[l][r]);
    if(ans>=2008)
    ans%=mod;
    }
    printf("%d\n",ans);
    }
    }
    int main()
    {
    int len;
    while(scanf("%d",&n)>0){
    len=0;
    for(int i=1;i<=n;i++){
    scanf("%d %d",&f[i].l,&f[i].r);
    num[++len]=f[i].l;
    num[++len]=f[i].r;
    }
    memset(mt.a,0,sizeof(mt.a));
    sort(num+1,num+len+1);
    sum=unique(num+1,num+1+len)-(num+1);
    for(int i=1;i<=n;i++){
    int l=EF(f[i].l);
    int r=EF(f[i].r);
    // printf("%d %d\n",l,r);
    mt.a[l][r]++;
    }
    MT[1]=mt;
    for(int i=2;i<=10000;i++){
    MT[i]=mat(mt,MT[i-1]);
    }
    solve();
    }
    return 0;
    }

  • 相关阅读:
    版本控制器 git
    JS 严格模式
    backquote
    linux内存监控 free
    好的linux网站
    linux查看进程开始时间
    命令之 ulimit
    using JSTL
    javax.servlet.jsp.PageContext cannot be resolved to a type
    jstl c
  • 原文地址:https://www.cnblogs.com/hgangang/p/11509324.html
Copyright © 2011-2022 走看看