HRBUST 2013 Winter Holiday Contest 5

来源:互联网 发布:易语言辅助中控台源码 编辑:程序博客网 时间:2024/06/03 10:39

 

 

A    首先读题不认真没有仔细的读数据范围,以为人家学校给大一训练的很简单轻敌了,结果交了2次后才发现是字符串的比较,唉 傻逼了。

       我用的是C++ STL string 比较容易,由于记不住什么qsort这神马的排序,写了个cmp就很容易过了。。。

 

#include<functional>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<numeric>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<list>
#include<set>
#include<map>

using namespace std;

string s[150];

bool cmp(const string & a,const string & b){
     if(a.size()==b.size()) return a<b;
     return a.size()<b.size();
}

int main(){
    int n;
    while(~scanf("%d",&n)){
      for(int i=0;i<n;i++) cin>>s[i];
      sort(s,s+n,cmp);
      for(int i=0;i<n;i++)
        cout<<s[i]<<endl;
    }
    return 0;
}

 

B 这题说的很清楚,就是字符串处理找神马的前缀。

两种解法:

1、建立字典树:ans=2*节点数+n(因为要输出n次)-最长链长度。用贪心的想法想局部,然后跳出来全局看,就得到这个结论了;


 2、将所有的单词按字典序排序,然后遍历;

 

*/

要不说我很弱,Tire看了么看明白也就只能用第二种方法了,过几天再把Tire贴上来。(占个坑)

 

#include<functional>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<numeric>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<list>
#include<set>
#include<map>


using namespace std;

string s[10005];


inline int cmp(string a,string b)
{
    int i;
    for(i=0;i<a.length()&&i<b.length()&&a[i]==b[i];i++);
    return a.length()-i+b.length()-i;
}   


int main()
{
    int n,i;
    while(~scanf("%d",&n))
    {
        for(i=0;i<n;i++)  cin>>s[i];
        sort(s,s+n);
        int sum=s[0].length()+1;
        int ANS=s[0].length();
        for(i=1;i<n;i++)
        {
            sum+=cmp(s[i],s[i-1])+1;
            if(s[i].length()>ANS)
               ANS=s[i].length();
        }
        printf("%d\n",sum+s[n-1].length()-ANS);  
    }   
    return 0;
}

 

 

C 这题我苦逼了。。。交了两次 唉 处理字符串不够细心,白白罚时。坑,真心很坑。。。

#include<functional>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<numeric>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<list>
#include<set>
#include<map>


using namespace std;

char a[101], str[101];

int main()
{
    int i, j;
    int t;
    scanf("%d", &t);
    getchar();
    while (t--)
    {
        gets(a);
        int len=strlen(a);
        i=0;j=0;
        while(a[i]==32) i++;
        if(islower(a[i])) str[j++]=a[i]-32;
        else str[j++]=a[i];
        i++;
         while(i<len-1)
        {
            if(a[i]==32&&a[i+1]!=32)
            {
                if(islower(a[i+1])) str[j++]=a[i+1]-32;
                else    str[j++]=a[i+1];
            }
            i++;
        }
        str[j]='\0';
        puts(str);
    }
    return 0;
}

 

D  这题傻逼了,时间到了 改明白了。。(思路应该是KMP  的Next数组性质,KMP 的算法。(我用的是LRJ的MP算法)),调了很久只因为花括号的地方放错了,所以一直WA、还是不细心啊。

 

#include<functional>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<numeric>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<list>
#include<set>
#include<map>


using namespace std;

const int MAXN=1000005;

char T[MAXN];

int F[MAXN];


void getfail(char *P,int *f)// MP算法
{
     f[0]=f[1]=0;
     int m=strlen(P);
     for(int i=1;i<m;i++){
       int j=f[i];
       while(j&&P[i]!=P[j]) j=f[j];
       f[i+1]=(P[i]==P[j]?j+1:0);
     }
}


int main(){
    char ch;
    int t;
    scanf("%d%*",&t);
    while(t--){
      scanf("%s",T);
      int len=strlen(T);
      getfail(T,F);
      bool flag=true;
      for(int i=2;i<=len;++i){
        if(F[i]>0&&i%(i-F[i])==0){
          printf("%d %d\n",i,i/(i-F[i]));flag=false;
        }
      }
      if(flag) cout<<"NO\n";
      cout<<endl;
    }
    return 0;
}

 

 

 

E  说是数学问题也可以。由于题中说的选定序列中的2个数ai,aj当然i!=j,然后它将ai増加1,将aj减少1,即ai=ai+1, aj=aj-1,以上的操作会改变该序列中的两个不同的元素,Tailmon可以进行上述操作无限次,只求将该序列中的数变成某一个数越多越好。现在他想知道通过上述操作无限多次最多能得到多少个相同的数

本质:无论你进行了多少次的ai=ai+1, aj=aj-1,其序列的Sum值是不会改变的,那么也就转化为了求Sum mod N 是否为0 或 1的问题。

if (Sum mod N = = 0 ) cout<<N<<endl;

 

else cout<< N-1<<endl;

 

#include<functional>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<numeric>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<list>
#include<set>
#include<map>


using namespace std;


int a[100005];

int main()
{
    int n;
    while(~scanf("%d",&n)){
      int sum=0;
      for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
      for(int i=1;i<=n;i++)
        sum+=a[i];
      if(sum%n) printf("%d\n",n-1);
      else printf("%d\n",n);
    }
    return 0;
}

 

 

F 这题又是字符串的模拟。。。细心就好。坑爹的字符串,伤不起。

 

#include<functional>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<numeric>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<list>
#include<set>
#include<map>

using namespace std;


char s[5000];

char t[5000];

int T,i;

int cnt=1;

bool flag;


int main()
{
   
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",s);
        flag=false;
        int len=strlen(s);
        int tmp=0;
        for(i=2;i<len;i++){
          if(flag==false&&s[i-2]==':'&&s[i-1]=='/'&&s[i]=='/'){
            flag=true;
            continue;
          }
          if(flag&&(s[i]=='/'||s[i]==':')) break;
          if(flag)  t[tmp++]=s[i];
        }  
        t[tmp]='\0';
        printf("Case #%d: %s\n",cnt++,t);    
    } 
    return 0;
}

 

 

G  终于来了到有难度的题,其实还是蛮简单的。给出函数,然后给出N个数a1,a2,a3……,问你其中F(ai)和F(aj) 相同的对数。其实就是求F(X) 二进制中X的1的个数。。。

#include<functional>
#include<algorithm>
#include<iostream>
#include<fstream>
#include<sstream>
#include<iomanip>
#include<numeric>
#include<cstring>
#include<cassert>
#include<cstdio>
#include<string>
#include<vector>
#include<bitset>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<list>
#include<set>
#include<map>

using namespace std;

int a[100003];

int check(int i){
    if(i==0)return 0;
    else return check(i>>1)+(i&1);
}

int main(){
    int n,i;
    while(~scanf("%d",&n)){
    for(i=0;i<n;i++)
      scanf("%d",&a[i]);
    for(i=0;i<n;i++)
      a[i]=check(a[i]);
    double ans=0.0,t=1.0;
    sort(a,a+n);
    for(i=1;i<n;i++)
      if(a[i]==a[i-1]) t+=1;
      else{
        ans+=((t*(t-1))/2);t=1;
      }
    {ans+=((t*(t-1))/2);t=1;}
    printf("%.0lf\n",ans);
    }
    return 0;
}

 

H   这题很傻逼。。。据说尼玛的3种解法(set+hash、用trie图统计字串、后缀数组)。。。而我傻逼的写了其中最长的后缀数组。这几天一直再看后缀数组,没想到这题成为了第一个A后缀数组的题。题目说的很清楚就是要寻找满足某一条件的不同字串个数。。。用后缀数组统计子串。。。。坑爹的是我废了很大劲写完了得到了FB,结果唉,人家把内存改大了,救了很多RE的孩子。。。真心坑。

 

#include<algorithm>
#include<cstring>
#include<cstdio>

using namespace std;

const int MAXN=2010;

char r[MAXN];

int sa[MAXN];

int wa[MAXN],wb[MAXN],wv[MAXN],ws[MAXN];

int height[MAXN],rank[MAXN];

int sum[2000],k;


inline bool cmp(int *r,int a,int b,int len){
    return r[a]==r[b]&&r[a+len]==r[b+len];
}


void SA(int n,int m){
    int i,j,p,*x=wa,*y=wb,*t;
    for(i=0;i<m;i++)
        ws[i]=0;
    for(i=0;i<n;i++)
        ws[x[i]=r[i]]++;
    for(i=1;i<m;i++)
        ws[i]+=ws[i-1];
    for(i=n-1;i>=0;i--)
        sa[--ws[x[i]]]=i;
    for(j=p=1;p<n;j<<=1,m=p){
        for(p=0,i=n-j;i<n;i++)
            y[p++]=i;
        for(i=0;i<n;i++){
            if(sa[i]>=j)
                y[p++]=sa[i]-j;
        }
        for(i=0;i<m;i++)
            ws[i]=0;
        for(i=0;i<n;i++)
            ws[wv[i]=x[y[i]]]++;
        for(i=1;i<m;i++)
            ws[i]+=ws[i-1];
        for(i=n-1;i>=0;i--)
            sa[--ws[wv[i]]]=y[i];
        for(t=x,x=y,y=t,x[sa[0]]=0,p=i=1;i<n;i++)
            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    }
}


void Height(int n){
    int i,j,k=0;
    for(i=1;i<=n;i++)
        rank[sa[i]]=i;
    for(i=0;i<n;height[rank[i++]]=k)
        for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
}


void solve(int n){
    int i,j;
    int ans=0;
    for(i=1;i<=n;i++){
        for(j=sa[i]+height[i];j<n;j++){
            if(sum[j+1]-sum[sa[i]]>k)break;
            ans++;
        }
    }
    printf("%d\n",ans);
}


int main(){
    while(~scanf("%s",r)){
      int i,j,n;
      char str[50];
      memset(sum,0,sizeof(sum));
      scanf("%s",str);
      scanf("%d",&k);
      n=strlen(r);
      for(i=1;i<=n;i++)
        sum[i]=sum[i-1]+(str[r[i-1]-'a']=='0');
      memset(height,0,sizeof(height));
      SA(n+1,130);
      Height(n);
      solve(n);
    }
    return 0;
}

总结:比赛还是思维反应的比较慢,还需要加强!!!算法估计的不是很准确。慢慢提高吧。