zoukankan      html  css  js  c++  java
  • 2016百度之星资格赛题解

    题目:Problem A

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=5685

    题意:对于一个字符串,定义一个哈希值 ∏是连乘,给一个字符串s,现有n个操作,每次操作询问下标 l 到 r 之间的子串的哈希值,前缀的思想,先预处理出0到每一位的哈希值gi,现在只涉及到g[r]和g[l-1],不过因为涉及到取模操作,所以不能直接除,应该找g[l-1]的逆元e,答案便是g[r]*e%9973。

     1 #include<stdio.h>
     2 char s[100010];
     3 int a[100010];
     4 int exGcd(int a,int b,int &x,int &y)
     5 {
     6   if(b==0)
     7   {
     8     x=1;
     9     y=0;
    10     return a;
    11   }
    12   int r=exGcd(b,a%b,x,y);
    13   int t=x;
    14   x=y;
    15   y=t-a/b*y;
    16   return r;
    17 }
    18 int main()
    19 {
    20   int n;
    21   while(scanf("%d",&n)!=EOF)
    22   {
    23     scanf("%s",s+1);
    24     a[0]=1;
    25     for(int i=1;s[i];i++)
    26     {
    27       a[i]=a[i-1]*(s[i]-28)%9973;
    28     }
    29     int x,y;
    30     while(n--)
    31     {
    32       scanf("%d%d",&x,&y);
    33       int l,r;
    34       exGcd(a[x-1],9973,l,r);
    35       l=(l%9973+9973)%9973;
    36       printf("%d
    ",a[y]*l%9973);
    37     }
    38   }
    39   return 0;
    40 }
    AC代码

    ===========================================

    题目:Problem B

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=5686

    题意:有一个只含有1的字符串,现在可以将任意相邻的1变为2,问可以形成多少种不同的字符串。比如111可以变为12,21,111。给你一个n表示1的数量,输出不同字符串的数量。

    思路:dp的水题,斐波拉契数列,大数。可以想象11111...可以分成(2)111...与1(1111)...,现在有两种情况:

      第一个1动:前两个1变为2,后面的111...再变,这种情况的数量是dp[n-2];

      第一个1不动:这种情况的数量是dp[n-1];

    注意:n很大,需要大数处理,只需要加法,而且时间限制也不是很紧,随便过。

     1 #include<stdio.h>
     2 #include<string.h>
     3 struct BigNum
     4 {
     5   int s[1000];
     6   int so;
     7   BigNum Add(BigNum b)
     8   {
     9     BigNum ret;
    10     memset(ret.s,0,sizeof(ret.s));
    11     ret.so=0;
    12     int i;
    13     for(i=0;i<so&&i<b.so;i++)
    14     {
    15       ret.s[i]+=s[i]+b.s[i];
    16       if(ret.s[i]>=10)
    17       {
    18         ret.s[ret.so]-=10;
    19         ret.s[++ret.so]=1;
    20       }
    21       else ret.so++;
    22     }
    23     for(;i<so;i++)
    24     {
    25       ret.s[i]=s[i]+ret.s[i];
    26       if(ret.s[i]>=10)
    27       {
    28         ret.s[ret.so]-=10;
    29         ret.s[++ret.so]=1;
    30       }
    31       else ret.so++;
    32     }
    33     for(;i<b.so;i++)
    34     {
    35       ret.s[i]=b.s[i]+ret.s[i];
    36       if(ret.s[i]>=10)
    37       {
    38         ret.s[ret.so]-=10;
    39         ret.s[++ret.so]=1;
    40       }
    41       else ret.so++;
    42     }
    43     if(ret.s[ret.so]!=0) ret.so++;
    44     return ret;
    45   }
    46   void get()
    47   {
    48     for(int i=so-1;i>=0;i--)
    49     {
    50       printf("%d",s[i]);
    51     }
    52   }
    53 };
    54 BigNum dp[210];
    55 int main()
    56 {
    57   dp[1].so=1;
    58   dp[1].s[0]=1;
    59   dp[2].so=1;
    60   dp[2].s[0]=2;
    61   for(int i=3;i<201;i++)
    62   {
    63     dp[i]=dp[i-1].Add(dp[i-2]);
    64   }
    65   int n;
    66   while(scanf("%d",&n)!=EOF)
    67   {
    68     dp[n].get();
    69     printf("
    ");
    70   }
    71   return 0;
    72 }
    AC代码

    ===========================================

    题目:Problem C

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=5687

    题意:有三种操作,一是 添加一个单词s ,二是 删除所有前缀是s的单词 ,三是 询问是否存在前缀为s的单词。

    思路:字典树,添加单词时,每一个前缀的num++,也就是如果此时sa的num为10,就说明前缀为sa的单词共有10个。删除所有前缀为s的单词时直接把s对应的num置0,要注意三点:

      一:这样删除的话添加单词abcdefg时,如果遇到abc的num为0,说明没有以abc为前缀的单词,所以应该将0向下更新,也就是说如果之前存在过abce,也就是此时abce的num是1,我添加abcdef时应该把abce更新为0,之所以要现在才更新是为了节省时间,不然会超时,注意只需要更新一层就够。

      二:删除abcd,置abcd的num为0,要向上更新,都减去abcd的num值。

      三:删除abcd,如果abc的num为0,说明没有abcd的存在,不能再往下进行,因为下面的num值都是假的。

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<stdlib.h>
      4 #include<algorithm>
      5 using namespace std;
      6 struct Node
      7 {
      8   int num;
      9   Node *fa;
     10   Node *next[26];
     11 };
     12 Node root;
     13 
     14 void Init()
     15 {
     16   root.num=0;
     17   for(int i=0;i<26;i++)
     18   {
     19     root.next[i]=NULL;
     20   }
     21 }
     22 
     23 Node *create(Node *fa)
     24 {
     25   Node *s=(Node*)malloc(sizeof(Node));
     26   s->fa=fa;
     27   s->num=0;
     28   for(int i=0;i<26;i++)
     29   {
     30     s->next[i]=NULL;
     31   }
     32   return s;
     33 }
     34 
     35 void Add(char *s)
     36 {
     37   Node *p=&root;
     38   for(int i=0;s[i];i++)
     39   {
     40     int pos=s[i]-'a';
     41     if(p->next[pos]==NULL)
     42     {
     43       p->next[pos]=create(p);
     44     }
     45     p=p->next[pos];
     46     if(p->num==0)
     47     {
     48       for(int j=0;j<26;j++)
     49       {
     50         if(p->next[j]!=NULL)
     51         {
     52           p->next[j]->num=0;
     53         }
     54       }
     55     }
     56     p->num++;
     57   }
     58 }
     59 
     60 void del(char *s)
     61 {
     62   Node *p=&root;
     63   for(int i=0;s[i];i++)
     64   {
     65     int pos=s[i]-'a';
     66     if(p->next[pos]==NULL) return ;
     67     else p=p->next[pos];
     68     if(p->num==0) return ;
     69   }
     70   int tmp=p->num;
     71   while(p!=&root)
     72   {
     73     p->num-=tmp;
     74     p=p->fa;
     75   }
     76 }
     77 
     78 bool find(char *s)
     79 {
     80   Node *p=&root;
     81   for(int i=0;s[i];i++)
     82   {
     83     int pos=s[i]-'a';
     84     if(p->next[pos]==NULL) return false;
     85     else p=p->next[pos];
     86     if(p->num==0) return false;
     87   }
     88   return true;
     89 }
     90 
     91 int main()
     92 {
     93   int n;
     94   char s[41],s1[10];
     95   scanf("%d",&n);
     96   Init();
     97   while(n--)
     98   {
     99     scanf("%s%s",s1,s);
    100     if(s1[0]=='i')
    101     {
    102       Add(s);
    103     }
    104     else if(s1[0]=='s')
    105     {
    106       if(find(s)) printf("Yes
    ");
    107       else printf("No
    ");
    108     }
    109     else
    110     {
    111       del(s);
    112     }
    113   }
    114   return 0;
    115 }
    AC代码

    ===========================================

    题目:Problem D

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=5688

    题意:定义ACM和CAM相同,也就是说通过ACM这三个字母全排列出来的所有字符串都相同,也就是只要是由ACM组成的字符串都相同。现在有n个操作,添加字符串s,同时输出这个字符串前面添加过多少次。

    思路:字典树,全排列都相同,那么可以先对字符串s进行排序,这样就只需要统计s出现的次数。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stdlib.h>
     4 #include<algorithm>
     5 using namespace std;
     6 struct Node
     7 {
     8   int num;
     9   Node *next[26];
    10 };
    11 Node root;
    12 void Init()
    13 {
    14   root.num=0;
    15   for(int i=0;i<26;i++)
    16     root.next[i]=NULL;
    17 }
    18 void Add(char *s)
    19 {
    20   Node *p=&root;
    21   for(int j=0;s[j];j++)
    22   {
    23     int i=s[j]-'A';
    24     if(p->next[i]==NULL)
    25     {
    26       Node *s=(Node *)malloc(sizeof(Node));
    27       for(int i=0;i<26;i++)
    28         s->next[i]=NULL;
    29       s->num=0;
    30       p->next[i]=s;
    31     }
    32     p=p->next[i];
    33   }
    34   p->num++;
    35   printf("%d
    ",p->num-1);
    36 }
    37 
    38 int main()
    39 {
    40   int n;
    41   char s[41];
    42   scanf("%d",&n);
    43   while(n--)
    44   {
    45     scanf("%s",s);
    46     sort(s,s+strlen(s));
    47     Add(s);
    48   }
    49   return 0;
    50 }
    AC代码

    ===========================================

    题目:Problem E

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=5689

    题意:有n个集合,每个集合由一个字符串表示,字符串表示分为复合条件和简单条件,简单条件就是由 变量 + 比较符 + 数字组成,复合条件就是通过逗号将简单条件并在一起,比如a<100,a>20,最终a的区间就是(20,100),现在问前i-1条(每一条)和第i条的交集是否为空,如果都为空就输出unique,否则就从小到大输出有交集的集合的编号。判断两个集合是否有交集就是说是否有相同变量的区间有重叠,比如第一条是a<100,第二条是a>50,那么这两个集合由交集。

    坑:如果第一条是a<100,第二条里没有出现a的限制,那么有交集。。。题目设定

    坑:如果第一条是a<100,第二条是a<10,b<100,b==100,第二条是空集,因为不存在合法的b,所以两条集合也没有交集。。。

    思路:记录每一条记录的每一个变量的左右区间就行,时间很松。完全可以1000*1000*30*log(30),就是对每一个集合遍历前面所有的集合,再遍历每一个变量,判断是否有交集,用map记录,不然比较变量名会花很多时间。(题目理清楚,写下去就很简单了)

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<map>
      4 #include<string>
      5 using namespace std;
      6 
      7 struct Node
      8 {
      9   char s[35];
     10   int l,r;
     11   bool flag;
     12 };
     13 
     14 Node a[1010][35];
     15 int ao[1010];
     16 bool ff[1010];
     17 map<string,int> m[1010];
     18 
     19 int mo;
     20 void solve(int pos,char *s)
     21 {
     22   for(int i=0;s[i];i++)
     23   {
     24     if(s[i]<='z'&&s[i]>='a')
     25     {
     26       char t[35];
     27       int j;
     28       for(j=i;s[j];j++)
     29       {
     30         if(s[j]<='z'&&s[j]>='a') t[j-i]=s[j];
     31         else break;
     32       }
     33       t[j-i]=0;
     34       int to;
     35       if(m[pos].find(t)==m[pos].end())
     36       {
     37         m[pos][t]=++mo;
     38         strcpy(a[pos][mo].s,t);
     39         a[pos][mo].l=-10000;
     40         a[pos][mo].r=10000;
     41         a[pos][mo].flag=1;
     42         to=mo;
     43         ao[pos]=mo;
     44       }
     45       else to=m[pos][t];
     46       int flag=0;
     47       for(;s[j];j++)
     48       {
     49         if(s[j]=='<'&&s[j+1]=='=') flag=2;
     50         else if(s[j]=='<') flag=1;
     51         else if(s[j]=='>'&&s[j+1]=='=') flag=4;
     52         else if(s[j]=='>') flag=3;
     53         else if(s[j]=='='&&s[j+1]=='=') flag=5;
     54         if(flag!=0) break;
     55       }
     56       int k=0,fu=1;
     57       for(j++;s[j];j++)
     58       {
     59         if(s[j]=='-')
     60         {
     61           fu=-1;
     62         }
     63         else if(s[j]<='9'&&s[j]>='0')
     64         {
     65           k=k*10+s[j]-'0';
     66         }
     67         else if(s[j]==',') break;
     68       }
     69       k=k*fu;
     70       if(flag==1) k--;
     71       else if(flag==3) k++;
     72       if(flag==1||flag==2)
     73       {
     74         a[pos][to].r=min(k,a[pos][to].r);
     75       }
     76       else if(flag==3||flag==4)
     77       {
     78         a[pos][to].l=max(k,a[pos][to].l);
     79       }
     80       else if(flag==5)
     81       {
     82         if(a[pos][to].l>k||a[pos][to].r<k) a[pos][to].flag=0;
     83         else
     84         {
     85           a[pos][to].l=k;
     86           a[pos][to].r=k;
     87         }
     88       }
     89       if(a[pos][to].l>a[pos][to].r) a[pos][to].flag=0;
     90       if(a[pos][to].flag==0) ff[pos]=1;
     91       i=j-1;
     92     }
     93   }
     94 }
     95 
     96 int main()
     97 {
     98   int n;
     99   char s[100];
    100   while(scanf("%d",&n)!=EOF)
    101   {
    102     getchar();
    103     memset(ff,0,sizeof(ff));
    104     for(int i=0;i<n;i++)
    105     {
    106       mo=0;
    107       gets(s);
    108       solve(i,s);
    109     }
    110     for(int i=0;i<n;i++)
    111     {
    112       bool flag=0;
    113       for(int u=0;u<i;u++)
    114       {
    115         if(ff[i]==1) continue;
    116         if(ff[u]==1) continue;
    117         int j;
    118         for(j=1;j<=ao[i];j++)
    119         {
    120           if(a[i][j].flag==0) break;
    121           int pos=m[u][a[i][j].s];
    122           if(pos==0) break;
    123           if(a[i][j].r<a[u][pos].l||a[i][j].l>a[u][pos].r);
    124           else break;
    125         }
    126         if(j>ao[i]);
    127         else
    128         {
    129           if(flag==1) printf(" ");
    130           flag=1;
    131           printf("%d",u+1);
    132         }
    133       }
    134       if(flag==0) printf("unique
    ");
    135       else printf("
    ");
    136     }
    137   }
    138   return 0;
    139 }
    AC代码
  • 相关阅读:
    红黑树-插入篇
    并查集
    Rabin-Karp【转载】
    KMP
    怎样花两月时间去应聘互联网公司 [转载]
    c++ 智能指针【转载】
    java序列化
    Web页面导出Excel表格
    基于jquery-UI的日期选择器
    Doc命令
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/5499621.html
Copyright © 2011-2022 走看看