2017 Multi-University Training Contest 2.Balala Power!(贪心)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6034
分析:做了半天才发现贪心得不对。。先处理出每一位出现的字符各有多少个,然后对超过26个的进位一下!!!类似桶排的做法从大到小排序一下就可以了,注意如果最小的出现在前导位置上,往前推到非前导的为止,然后把经过的全部+1,把非前导的那个当0。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 typedef long long ll; 7 const int mod=1e9+7,maxn=1e5+5; 8 int n; 9 char s[maxn]; 10 ll coun[maxn][26]; 11 ll to[26]; 12 ll r[26]; 13 long long ans=0; 14 int len=0,idx; 15 bool Is_same[maxn],Is_start[26]; 16 bool Cmp(ll a,ll b){ 17 return coun[idx][a]>coun[idx][b]; 18 } 19 void solve(){ 20 for(int i=0;i<26;i++)Is_same[i]=true; 21 for(int j=0;j<26;j++){ 22 int c=0; 23 for(int i=maxn-1;i>=maxn-len;i--){ 24 if(coun[i][j]>=26){ 25 if(i==maxn-len)len++; 26 coun[i-1][j]+=coun[i][j]/26; 27 coun[i][j]%=26; 28 29 } 30 } 31 } 32 ans=0; 33 int s=0,t=0; 34 idx=maxn-len; 35 sort(r,r+26,Cmp); 36 for(int i=maxn-len+1;i<maxn;i++){ 37 s=0; 38 while(s<25){ 39 t=s; 40 while(t<25&&Is_same[t]&&coun[i-1][r[t]]==coun[i-1][r[t+1]]) 41 t++; 42 if(s!=t){ 43 idx=i; 44 sort(r+s,r+t+1,Cmp); 45 } 46 Is_same[t]=false; 47 s=t+1; 48 } 49 } 50 if(Is_start[r[25]]){ 51 int i=24; 52 while(Is_start[r[i]]) 53 i--; 54 int q=r[i]; 55 for(int j=i+1;j<26;j++) 56 r[j-1]=r[j]; 57 r[25]=q; 58 } 59 for(int i=0;i<26;i++){ 60 to[r[i]]=25-i; 61 } 62 for(int i=maxn-len;i<maxn;i++){ 63 ans=(ans*26)%mod; 64 for(int j=0;j<26;j++){ 65 ans=(ans+coun[i][j]*to[j])%mod; 66 } 67 } 68 } 69 int main(){ 70 //freopen("e:\\in.txt","r",stdin); 71 int kase=0; 72 while(scanf("%d",&n)!=EOF){ 73 len=0; 74 memset(coun,0,sizeof(coun)); 75 memset(Is_start,0,sizeof(Is_start)); 76 memset(to,-1,sizeof(to)); 77 for(int i=0;i<26;i++) 78 r[i]=i; 79 for(int i=0;i<n;i++){ 80 scanf("%s",s); 81 int l=strlen(s); 82 len=max(len,l); 83 if(l>1) 84 Is_start[s[0]-'a']=true; 85 for(int j=1;j<=l;j++){ 86 coun[maxn-j][s[l-j]-'a']++; 87 } 88 } 89 solve(); 90 cout<<"Case #"<<++kase<<": "<<ans<<endl; 91 } 92 return 0; 93 }