zoukankan      html  css  js  c++  java
  • 2013 Multi-University Training Contest 4 部分解题报告

    problem 1001(hdu 4632)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=4632

    Palindrome subsequence

    思路:记忆化DP,

    dp[i][j]表示原字符串中[i,j]位置中出现的回文子序列的个数

     

    递推关系:

     

    dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]

    如果str[i]==str[j]

    dp[i][j]+=dp[i+1][j-1]

     1 #include <iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 const int maxn=1010;
     6 const int mod=10007;
     7 int dp[maxn][maxn];
     8 char str[maxn];
     9 int dfs(int l,int r)
    10 {
    11     if(dp[l][r]!=-1)
    12     return dp[l][r];
    13     if(l==r)
    14     {
    15         dp[l][r]=1;
    16         return dp[l][r];
    17     }
    18     if(l+1==r)
    19     {
    20         if(str[l]==str[r])
    21         {
    22             dp[l][r]=3;
    23         }
    24         else
    25         dp[l][r]=2;
    26         return dp[l][r];
    27     }
    28     int t=dfs(l+1,r-1);
    29     dp[l][r]=0;
    30     dp[l][r]+=dfs(l+1,r)+dfs(l,r-1)-t;
    31     if(str[l]==str[r])
    32     dp[l][r]+=t+1;
    33     dp[l][r]%=mod;
    34     if(dp[l][r]<0)//一开始没有考虑到
    35     dp[l][r]+=mod;
    36     return dp[l][r];
    37 }
    38 int main()
    39 {
    40     int T;
    41     scanf("%d",&T);
    42     int k=0;
    43     while(T--)
    44     {
    45         getchar();
    46         scanf("%s",str);
    47         k++;
    48         int len=strlen(str);
    49         memset(dp,-1,sizeof(dp));
    50         printf("Case %d: %d
    ",k,dfs(0,len-1));
    51     }
    52     return 0;
    53 }
    View Code

    problem 1004(hdu 4635)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=4635

    Strongly connected

    思路:利用tarjan算法,将图分成多个强连通分量子图,查找出出度或入度为零并且子图点数最少的连通分量子图(假设称为最小子图),其点数为mmin

       将除最小子图的剩余部分连成完全有向图,把最小子图的点之间连成完全有向图,最后只用单向边连接两部分,减去原来的边数m即可;

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<vector>
      6 #include<stack>
      7 using namespace std;
      8 const int maxn=100010;
      9 struct node
     10 {
     11     int u;
     12     int v;
     13     int next;
     14 }edge[maxn];
     15 int head[maxn];
     16 int in[maxn],out[maxn];
     17 int dfn[maxn];
     18 int low[maxn];
     19 int sccno[maxn];
     20 int num[maxn];
     21 int cn,deep,sccnum;
     22 stack<int>st;
     23 void init()
     24 {
     25     memset(head,-1,sizeof(head));
     26     memset(dfn,0,sizeof(dfn));
     27     memset(sccno,0,sizeof(sccno));
     28     memset(in,0,sizeof(in));
     29     memset(out,0,sizeof(out));
     30     memset(num,0,sizeof(num));
     31     deep=0;
     32     sccnum=0;
     33     cn=0;
     34     while(!st.empty())
     35     {
     36         st.pop();
     37     }
     38 }
     39 void add(int u,int v)
     40 {
     41     edge[cn].u=u;
     42     edge[cn].v=v;
     43     edge[cn].next=head[u];
     44     head[u]=cn++;
     45 }
     46 void tarjan(int u)
     47 {
     48     st.push(u);
     49     low[u]=dfn[u]=++deep;
     50     int i;
     51     for(i=head[u];i!=-1;i=edge[i].next)
     52     {
     53         int v=edge[i].v;
     54         if(!dfn[v])
     55         {
     56             tarjan(v);
     57             low[u]=min(low[u],low[v]);
     58         }
     59         else if(!sccno[v])
     60         {
     61             low[u]=min(low[u],dfn[v]);
     62         }
     63     }
     64     if(low[u]==dfn[u])
     65     {
     66         sccnum++;
     67         while(1)
     68         {
     69             int x=st.top();
     70             st.pop();
     71             sccno[x]=sccnum;
     72             if(x==u)
     73             break;
     74         }
     75     }
     76 }
     77 int main()
     78 {
     79     int T;
     80     scanf("%d",&T);
     81     int k=0;
     82     while(T--)
     83     {
     84         __int64 m,n;
     85         scanf("%I64d%I64d",&n,&m);
     86         k++;
     87 
     88         int i,j;
     89 
     90         init();
     91         for(i=0;i<m;i++)
     92         {
     93             int u,v;
     94             scanf("%d%d",&u,&v);
     95             add(u,v);
     96         }
     97         for(i=1;i<=n;i++)
     98         {
     99             if(!dfn[i])
    100             {
    101                tarjan(i);
    102             }
    103         }
    104         //printf("scc=%d",sccnum);
    105         if(sccnum==1)
    106         {
    107             printf("Case %d: -1
    ",k);
    108             continue;
    109         }
    110         for(i=1;i<=n;i++)
    111         {
    112             num[sccno[i]]++;
    113             for(j=head[i];j!=-1;j=edge[j].next)
    114             {
    115                 int v=edge[j].v;
    116                 if(sccno[i]!=sccno[v])
    117                 {
    118                     out[sccno[i]]++;
    119                     in[sccno[v]]++;
    120                 }
    121             }
    122         }
    123         __int64 mmin=1e13;
    124         for(i=1;i<=sccnum;i++)
    125         {
    126             if(in[i]==0||out[i]==0)
    127             {
    128                 if(mmin>num[i])
    129                 mmin=num[i];
    130             }
    131         }
    132         __int64 res=0;
    133         res+=(n-mmin)*(n-mmin-1);
    134         res+=mmin*(mmin-1);
    135         res+=(n-mmin)*mmin;
    136         res-=m;
    137         printf("Case %d: %I64d
    ",k,res);
    138     }
    139 }
    View Code

     problem 1007(hdu 4638)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=4638

    思路:(官方题解)

    题意为询问一段区间里的数能组成多少段连续的数。先考虑从左往右一个数一个数添加,考虑当前添加了i - 1个数的答案是x,那么添加完i个数后的答案是多少?可以看出,是根据a[i]-1a[i]+1是否已经添加而定的,如果a[i]-1或者a[i]+1已经添加一个,则段数不变,如果都没添加则段数加1,如果都添加了则段数减1。设v[i]为加入第i个数后的改变量,那么加到第x数时的段数就是sum{v[i]} (1<=i<=x}。仔细想想,若删除某个数,那么这个数两端的数的改变量也会跟着改变,这样一段区间的数构成的段数就还是他们的v值的和。将询问离线处理,按左端点排序后扫描一遍,左边删除,右边插入,查询就是求区间和。

     

      1 #include <iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 const int maxn=100010;
      7 int data[maxn];
      8 int pos[maxn];
      9 int in[maxn];
     10 int tree[maxn];
     11 int ss[maxn];
     12 int res[maxn];
     13 int n,m;
     14 struct node
     15 {
     16     int l;
     17     int r;
     18     int xh;
     19 } que[maxn];
     20 bool cmp(struct node a,struct node b)
     21 {
     22     if(a.l==b.l)
     23         return a.r<b.r;
     24     else
     25         return a.l<b.l;
     26 }
     27 int lowbit(int x)
     28 {
     29     return x&(-x);
     30 }
     31 void update(int s,int num)
     32 {
     33     while(s<=n)
     34     {
     35         tree[s]+=num;
     36         s+=lowbit(s);
     37     }
     38 }
     39 int query(int s)
     40 {
     41     int sum=0;
     42     while(s>0)
     43     {
     44         sum+=tree[s];
     45         s-=lowbit(s);
     46     }
     47     return sum;
     48 }
     49 int main()
     50 {
     51     int T;
     52     scanf("%d",&T);
     53     while(T--)
     54     {
     55         memset(tree,0,sizeof(tree));
     56         memset(pos,0,sizeof(pos));
     57         scanf("%d%d",&n,&m);
     58         int i;
     59         for(i=1; i<=n; i++)
     60         {
     61             scanf("%d",&data[i]);
     62             pos[data[i]]=i;
     63         }
     64         int l,r;
     65         for(i=0; i<m; i++)
     66         {
     67             scanf("%d%d",&l,&r);
     68             que[i].l=l;
     69             que[i].r=r;
     70             que[i].xh=i;
     71         }
     72         sort(que,que+m,cmp);
     73         memset(in,0,sizeof(in));
     74         memset(ss,0,sizeof(ss));
     75         for(i=1; i<=n; i++)
     76         {
     77             if(in[data[i]-1])ss[i]++;
     78             if(in[data[i]+1])ss[i]++;
     79             if(ss[i]==0)
     80                 update(i,1);
     81             if(ss[i]==2)
     82                 update(i,-1);
     83             in[data[i]]=1;
     84         }
     85         l=1;
     86         for(i=0; i<m; i++)
     87         {
     88             for(; l<que[i].l; l++)
     89             {
     90                 if(data[l]>1&&pos[data[l]-1]>l)
     91                 {
     92                     update(pos[data[l]-1],1);
     93                 }
     94                 if(data[l]<n&&pos[data[l]+1]>l)
     95                 {
     96                     update(pos[data[l]+1],1);
     97                 }
     98             }
     99             res[que[i].xh]=query(que[i].r)-query(que[i].l-1);
    100         }
    101         for(i=0; i<m; i++)
    102         {
    103             printf("%d
    ",res[i]);
    104         }
    105     }
    106     return 0;
    107 }
    View Code

     

     

    problem 1008(hdu 4639)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=4639

    Hehe

    思路:hehe个数是1,hehehe的个数是2,hehehehe的个数是3。那么表示的意思的种数分别是2,3,5可以推出斐波纳挈数列

    将字符串里的统计连续hehe的数量,,再相乘即可

     1 #include <iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 const int maxn=10100;
     6 const int mod=10007;
     7 char str[maxn];
     8 int st[maxn];
     9 void init()
    10 {
    11     int i;
    12     st[0]=0;
    13     st[1]=2;
    14     st[2]=3;
    15     for(i=3;i<=10090;i++)
    16     {
    17         st[i]=(st[i-2]+st[i-1])%mod;
    18     }
    19 }
    20 int run()
    21 {
    22     int len=strlen(str);
    23     int i;
    24     int num=0;
    25     int sum=1;
    26     for(i=0;i<len-3;)
    27     {
    28         if(str[i]=='h'&&str[i+1]=='e'&&str[i+2]=='h'&&str[i+3]=='e')
    29         {
    30             num++;
    31             i+=2;
    32         }
    33         else
    34         {
    35             if(num!=0)
    36             sum=sum*st[num]%mod;
    37             num=0;
    38             i++;
    39         }
    40     }
    41     if(num!=0)
    42     sum=sum*st[num]%mod;
    43     return sum;
    44 }
    45 int main()
    46 {
    47     int T,k=0;
    48     scanf("%d",&T);
    49     init();
    50     while(T--)
    51     {
    52         getchar();
    53         scanf("%s",str);
    54         k++;
    55         printf("Case %d: %d
    ",k,run());
    56     }
    57     return 0;
    58 }
    View Code

    problem 1011(hdu 4642)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=4642

    Fliping game

    思路:只需要判断map[m][n]是0还是1即可,0则Bob胜,否则Alice胜

    因为不管翻动哪一个盒子,总会反动到右下角的那个,当右下角是1时,需翻动奇数次盒子才能翻成0,当右下角是0时,需翻动偶数次盒子才能翻成0

     1 #include <iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 int main()
     6 {
     7     int T;
     8     scanf("%d",&T);
     9     while(T--)
    10     {
    11         int n,m;
    12         scanf("%d%d",&n,&m);
    13         int a;
    14         for(int i=0;i<n;i++)
    15         {
    16             for(int j=0;j<m;j++)
    17             {
    18                 scanf("%d",&a);
    19             }
    20         }
    21         if(a==1)
    22         printf("Alice
    ");
    23         else
    24         printf("Bob
    ");
    25     }
    26     return 0;
    27 }
    View Code

     

  • 相关阅读:
    书列君荐书|《福尔摩斯探案大全集》.(英)阿瑟.柯南道尔.扫描版
    anaconda同时集成Python2 和 Python3
    python 使用sqlite,ConfigParser实例
    python 爬虫爬取历年双色球开奖信息
    关于python 爬虫遇到的反盗链
    CentOS7搭建Docker私有仓库----Docker
    Ansible + shell 实现部署fastdfs+nginx 实现图片服务器并提供动态缩放功能;
    python+fastdfs+nginx实现打包下载功能
    监控生产服务器内存使用前十
    python操作MySQL--实例
  • 原文地址:https://www.cnblogs.com/wanglin2011/p/3233230.html
Copyright © 2011-2022 走看看