zoukankan      html  css  js  c++  java
  • bzoj5000 OI树

    Description

    几天之后小跳蚤即将结束自己在lydsy星球上的旅行。这时,lydsy人却发现他们的超空间传送装置的能量早在小跳蚤通过石板来到lydsy星球时就已经消耗光了。这时,小跳蚤了解到自己很有可能回不到跳蚤国了,于是掉下了伤心的眼泪……lydsy人见状决定无论如何也要送小跳蚤回地球,于是lydsy人的大祭司lavendir决定拜访lydsy星球的OI树,用咒语从OI树中取得能量。咒语中有K种字母,我们用前K个大写英文字母来表示它。OI树可以被认为是一个有着N个节点的带权有向图,所有节点的出度都是K,并且所有的出边都对应于一个咒语中的字母。仪式开始的时候有一个标记物放在OI树的1号节点上。之后,从咒语的第一个字母开始,每经过一个字母,标记物就沿着该字母对应的出边进入这条边的终点,并且得到相当于边权大小的能量值。当咒语处理完毕时,就可以得到这个过程中得到的所有能量了。现在由于lydsy人超群的计算能力,他们已经知道某咒语大概会获得多少能量,只是还想知道会获得的能量值对一个数M取模的结果。跳蚤国王通过小跳蚤留下的石板也了解到了小跳蚤现在的处境,所以他又找到了你,希望你帮助他计算出这个问题的答案。

    Input

    第一行是两个空格分隔的整数N和K。
    之后N行每行2*K个整数A_1,B_1,A_2,B_2,...,A_K,B_K,表示N个节点的K条出边。
    第i行表示第 i-1 个节点,这一行的A_S,B_S的值表示第S个大写字母对应的出边的终点为A_S,权值为B_S。
    下面一行有一个字符串,表示咒语。
    由于咒语的长度会非常长,将采用压缩方式给出,用[SA]表示连续S个字母A,S是一个正整数,A是单个字母。
    比如说,字符串[5A]BC[3A][3C]表示的咒语为AAAAABCAAACCC。
    之后一个正整数M,表示取模的底数。
    字符串长度≤120000,在一个压缩节[SA]中,S≤10^9。K≤26,N≤10000,M≤10^9,所有边的权值小于10^9

    Output

    一个整数,表示问题的答案。

    Sample Input

    4 2
    3 3 2 5
    1 7 3 2
    4 3 2 5
    2 10 3 2
    [3A]B[2A][2B]
    10000

    Sample Output

    38


    正解:倍增。

    比较裸的题,直接对于每一段路,倍增算出答案即可。

     1 #include <bits/stdc++.h>
     2 #define il inline
     3 #define RG register
     4 #define ll long long
     5 
     6 using namespace std;
     7 
     8 int f[26][31][10010],v[26][31][10010],n,k,len,rhl,ans;
     9 char s[150010];
    10 
    11 il int gi(){
    12   RG int x=0,q=1; RG char ch=getchar();
    13   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    14   if (ch=='-') q=-1,ch=getchar();
    15   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    16   return q*x;
    17 }
    18 
    19 int main(){
    20 #ifndef ONLINE_JUDGE
    21   freopen("OItree.in","r",stdin);
    22   freopen("OItree.out","w",stdout);
    23 #endif
    24   n=gi(),k=gi();
    25   for (RG int i=1;i<=n;++i)
    26     for (RG int j=0;j<k;++j)
    27       f[j][0][i]=gi(),v[j][0][i]=gi();
    28   scanf("%s",s+1),len=strlen(s+1),rhl=gi();
    29   for (RG int p=0;p<k;++p)
    30     for (RG int j=1;j<=30;++j)
    31       for (RG int i=1;i<=n;++i){
    32     f[p][j][i]=f[p][j-1][f[p][j-1][i]];
    33     v[p][j][i]=v[p][j-1][f[p][j-1][i]]+v[p][j-1][i];
    34     if (v[p][j][i]>=rhl) v[p][j][i]-=rhl;
    35       }
    36   for (RG int i=1,jp,p,S=1;i<=len;){
    37     while (s[i]=='[') ++i; jp=0;
    38     while (s[i]>='0' && s[i]<='9') jp=jp*10+s[i]-48,++i;
    39     if (!jp) jp=1; p=s[i]-'A',++i; while (s[i]==']') ++i;
    40     for (RG int j=30;j>=0;--j)
    41       if (jp>=(1<<j)){
    42     jp-=1<<j,ans+=v[p][j][S],S=f[p][j][S];
    43     if (ans>=rhl) ans-=rhl;
    44       }
    45     if (i>len) break;
    46   }
    47   cout<<ans; return 0;
    48 }
  • 相关阅读:
    SQL语法 之 基本查询
    Oracle 之 常用函数
    Tomcat 之 启动tomcat时 错误: 代理抛出异常 : java.rmi.server.ExportException: Port already in use: 1099;
    vim 如何编辑 GB2312 编码的文件?
    网络编程常见类型定义
    网络地址转换相关函数使用(inet_addr,inet_ntoa,inet_addr)
    onvif获取摄像头的流媒体地址完整流程
    gsoap
    海康ipc onvif抓包分析
    onvif杂项
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7603443.html
Copyright © 2011-2022 走看看