hdu6034[模拟] 2017多校1

/*hdu6034[模拟] 2017多校1*/
//暴力模拟26个26进制数即可, 要注意进位
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const double eps=1e-8;
const int inf=0x3f3f3f3f;
struct node{
    char num[100005];
    int ch,high;
}bits[30];
const int mod=1000000007;
int n,len,pos,mark[30],w[30],kase=1;
char str[100005];
LL fastpow(LL a,LL b){
    LL ret=1,x=a;
    while(b){
        if(b&1){
            ret=(ret*x)%mod;
        }
        x=(x*x)%mod;
        b>>=1;
    }
    return ret;
}
bool cmp(node a,node b){
    if(a.high!=b.high){
        return a.high>b.high;
    }
    else{
        for(int i=a.high-1;i>=0;i--){
            if(a.num[i]>b.num[i]){
                return 1;
            }
            else if(a.num[i]<b.num[i]){
                return 0;
            }
        }
    }
    return 0;
}
LL cal(node& a){
    LL ret=0;
    for(int i=0;i<a.high;i++){
        if(a.num[i]){
            ret=(ret+((LL)a.num[i]*fastpow(26LL,i))%mod)%mod;
        }
    }
    return ret;
}
void solve(){
    LL sum=0;
    sort(bits,bits+26,cmp);
    for(int i=0;i<26;i++){
        if(bits[i].high) w[bits[i].ch]=25-i;
        if(mark[bits[i].ch]&&w[bits[i].ch]==0){
            int pos=i;
            while(mark[bits[pos].ch]&&pos) pos--;
            for(int j=pos+1;j<26;j++) w[bits[j].ch]++;
            w[bits[pos].ch]=0;
        }
    }
    for(int i=0;i<26;i++){
        sum=(sum+w[bits[i].ch]*cal(bits[i]))%mod;
    }
    printf("Case #%d: %lld\n",kase++,sum);
}
int main(){
    while(~scanf("%d",&n)){
        memset(bits,0,sizeof(bits));
        memset(w,0,sizeof(w));
        memset(mark,0,sizeof(mark));
        for(int i=0;i<26;i++) bits[i].ch=i;
        for(int i=0;i<n;i++){
            scanf("%s",str);
            len=strlen(str);
            mark[str[0]-‘a‘]++;
            for(int i=0;i<len;i++){
                pos=len-i-1;
                bits[str[i]-‘a‘].high=max(bits[str[i]-‘a‘].high,pos+1);
                bits[str[i]-‘a‘].num[pos]++;
                while(pos<99999&&bits[str[i]-‘a‘].num[pos]>=26){
                    int k=bits[str[i]-‘a‘].num[pos]/26;
                    bits[str[i]-‘a‘].num[pos]-=26;
                    bits[str[i]-‘a‘].num[++pos]++;
                }bits[str[i]-‘a‘].high=max(bits[str[i]-‘a‘].high,pos+1);
            }
        }solve();
    }
    return 0;
}
时间: 2024-12-17 09:35:04

hdu6034[模拟] 2017多校1的相关文章

hdu6069[素数筛法] 2017多校3

/*hdu6069[素数筛法] 2017多校3*/ #include <bits/stdc++.h> using namespace std; typedef long long LL; LL l, r, k; const LL MOD = 998244353LL; int T, n, prime[1100000], primesize; bool isprime[11000000]; void getlist(int listsize) { memset(isprime, 1, sizeof

hdu6035[dfs+思维] 2017多校1

/*hdu6035[dfs+思维] 2017多校1*/ //合并色块, 妙啊妙啊 #include<bits/stdc++.h> using namespace std; const double eps=1e-8; const int inf=0x3f3f3f3f; typedef long long LL; vector<int>G[200005]; LL sum[200005]; int c[200005],son[200005],mark[200005]; int n,u,

hdu6078[优化递推过程] 2017多校4

/*hdu6078[优化递推过程] 2017多校4*/ #include <bits/stdc++.h> using namespace std; typedef long long LL; const LL MOD = 998244353LL; int T, m, n, a[2005], b[2005]; LL sum[2005][3], dp[2005][3]; void solve() { LL ans = 0; for (int i = 1; i <= n; i++) { LL

hdu6074[并查集+LCA+思维] 2017多校4

看了标答感觉思路清晰了许多,用并查集来维护全联通块的点数和边权和. 用另一个up[]数组(也是并查集)来保证每条边不会被重复附权值,这样我们只要将询问按权值从小到大排序,一定能的到最小的边权和与联通块中的点数. 下面是过程分析.过程中一共运用了两个并查集. [数据]110 31 21 32 42 53 63 74 85 95 109 6 3 1 501 4 2 5 209 10 8 10 40[分析]首先我们将图构建出来我们将m次询问按权值从小到大排序后: 1 4 2 5 209 10 8 10

【链表】2017多校训练3 HDU 6058 Kanade&#39;s sum

acm.hdu.edu.cn/showproblem.php?pid=6058 [题意] 给定一个排列,计算 [思路] 计算排列A中每个数的贡献,即对于每个ai,计算有ni个区间满足ai是区间中的第k大,那么ai对答案的贡献就是ai*ni 以ai为起点,统计ai右边离ai最近的,比ai大的k个数的位置 同理统计左边的位置,组合得到答案 关键是得到比ai大的离ai最近的k个数的位置 因为是排列,所以每个数都不相等,可以记录每个数的位置,然后从小到大枚举ai,这样维护一个双向链表,保证链表中的数就是

hdu6103[尺取法] 2017多校6

/*hdu6103[尺取法] 2017多校6*/ #include <bits/stdc++.h> using namespace std; int T, m; char str[20005]; void solve() { int ans = 0; int n = strlen(str); for (int i = 0; i < n; i++) { int l = 0, r = 0, p1 = i, p2 = i + 1, cost = 0; while (p1 - r >= 0

hdu6098[RMQ+筛法] 2017多校6

/*hdu6098[RMQ+筛法] 2017多校6*/ #include <bits/stdc++.h> using namespace std; int T, n, st[100005][20], len[100005], a[100005]; void st_init() { len[0] = -1; for (int i = 1; i <= n; i++) { st[i][0] = a[i]; len[i] = (i & (i - 1)) == 0 ? len[i - 1]

2017多校第一套&amp;&amp;hdu6038 思维 数学

链接  http://acm.hdu.edu.cn/showproblem.php?pid=6038 题意: 给你一个a序列,代表0到n-1的排列:一个b序列代表0到m-1的排列.问你可以找出多少种函数关系f,f的定义域内的i都满足f(i)=b[f(a[i])]; 分析:这个主要是找循环节 循环节导致函数有多种情况 找到每段循环节的 取值 种数 相乘起来就是答案比如说:如果 a 序列是 2 0 1 那么我们可以发现 f[0] = b[f(a[0])]     f[0]  = b[f(2)] f[

2017多校Round4(hdu6067~hdu6079)

补题进度:10/13 1001 待填坑 1002(kmp+递推) 题意: 有长度为n(<=50000)的字符串S和长度为m(m<=100)的字符串T,有k(k<=50000)组询问,每个询问(L,R),表示对于所有的(i,j)(1<=i<=L,R<=j<=n),将S[1..i]和S[j..n]拼接起来,求这个新的S'中出现T的次数总和 分析: 我们分析对于一个(i,j)的情况下,那么T的出现有三种情况,一种是整体在[1..i],第二种是整体在[j..n],第三种是