2017多校训练第一场

1.Add More Zero(HDU6033)

题目链接

题意求 10k<=2m1 的最小k,m已知,显然只要 k<=log(2m1) 就好,又因为2的次幂末位肯定比0大所以就变成了 k<=log(2m)

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define pi acos(-1)
#define maxn 111111
#define maxm 11111
#define INF 0x3F3F3F3F
#define eps 1e-8

#define pb push_back

#define mem(a) memset(a,0,sizeof a)

using namespace std;

const long long mod = 1000000007;
/**lyc**/
void init() {

}
int main() {
    int m;
    int kase = 0;
    while(scanf("%d", &m) != EOF) {
        int ans = m * log10(2);
        printf("Case #%d: %d\n", ++kase, ans);
    }
    return 0;
}

11.KazaQ’s Socks(HDU6043)

题目链接

题意:随便找一下规律,就是1-n然后1-(n-1)在1-(n-2),n后两者循环

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define pi acos(-1)
#define maxn 111111
#define maxm 11111
#define INF 0x3F3F3F3F
#define eps 1e-8

#define pb push_back

#define mem(a) memset(a,0,sizeof a)

using namespace std;

const long long mod = 1000000007;
/**lyc**/
void init() {

}
long long n, k;
int main() {
    int kase = 0;
    while(scanf("%lld%lld", &n, &k) != EOF) {
        if(k <= n) {
            printf("Case #%d: %lld\n", ++kase, k);
            continue;
        }
        k -= n;
        k = k % (2 * (n - 1));
        if(k == 0) k = 2 * (n - 1);
        if(k <= n - 1) {
            printf("Case #%d: %lld\n", ++kase, k);
        }
        else {
            k -= n - 1;
            if(k <= n - 2) {
                printf("Case #%d: %lld\n", ++kase, k);
            }
            else {
                printf("Case #%d: %lld\n", ++kase, n);
            }
        }
    }
    return 0;
}

2.Balala Power!(HDU6034)

题目链接

题意:对于n个字符串,其中有a-z 26个小写字母,然后对于其中出现过的字母,赋予0-25的值,然后每个字符串都是一个26进制的数,求n个字符串的最大值。

思路:显然我们从25开始赋值,对于贡献度大的优先赋值。然后要注意每个字符串首位不能是0的条件。这个可以开一个存储是否是头字母的数组实现。然后加一下判断就好。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define pi acos(-1)
#define maxn 111111
#define maxm 11111
#define INF 0x3F3F3F3F
#define eps 1e-8

#define pb push_back

#define mem(a) memset(a,0,sizeof a)

using namespace std;

const long long mod = 1000000007;
/**lyc**/
void init() {

}
char s[maxn];
int n;
int num[maxn][30];
bool tou[30];
bool vis[30];
int ans[30];
int maxa[maxn];
int temp[maxn];
bool cp(int *a, int *b, int len) {
    for(int i = len - 1; i >= 0; i--) {
        if(a[i] == b[i]) continue;
        if(a[i] > b[i]) return 1;
        else return 0;
    }
    return 1;
}
int main() {
    int kase = 0;
    while(scanf("%d", &n) != EOF) {
        int maxlen = 0;
        memset(num, 0, sizeof num);
        memset(tou, 0, sizeof tou);
        for(int i = 1; i <= n; i++) {
            scanf("%s", s);
            int len = strlen(s);
            maxlen = max(maxlen, len);
            tou[s[0] - 'a'] = 1;
            reverse(s, s + len);
            for(int j = 0; j < len; j++) {
                num[j][s[j] - 'a']++;
            }
        }
        int toun = 0;
        for(int i = 0; i < 26; i++)
            if(tou[i]) toun++;
        int fa = 0;///0是否被用
        memset(ans, 0, sizeof ans);
        memset(vis, 0, sizeof vis);
        //cout << "1*************" << endl;
        for(int i = 25; i >= 0; i--) {
            int pos = -1;
            if(fa && !i) break;
            memset(maxa, 0, (sizeof maxa[0]) * (maxlen + 10));
            for(int k = 0; k <= 25; k++) if(!vis[k]) {
              //  cout << k << endl;
                memset(temp, 0, (sizeof temp[0]) * (maxlen + 10));
                long long more = 0;
                for(int j = 0; j < maxlen - 1; j++) {
                    temp[j] = (1LL * num[j][k] * i + more) % 26;
                    more = (1LL * num[j][k] * i + more) / 26;

                }
                temp[maxlen - 1] = 1LL*num[maxlen - 1][k] * i + more;
                if(cp(temp, maxa, maxlen)) {
                    swap(temp, maxa);
                    pos = k;
                }
            }
           // cout << i << " " << pos << endl;
            if(!fa && !tou[pos]) {
                if(toun == i) {
                    ans[pos] = 0;
                    vis[pos] = 1;
                    i++;
                    fa = 1;
                    continue;
                }
            }
            ans[pos] = i;
            vis[pos] = 1;
            if(tou[pos]) toun--;
        }
       // cout << "2*************" << endl;
        long long tot = 0;
        long long bit = 1;
        for(int i = 0; i < maxlen; i++) {
            for(int j = 0; j < 26; j++) {
                tot += 1LL * bit * num[i][j] % mod * ans[j] % mod;
                if(tot >= mod) tot -= mod;
            }
            bit *= 26;
            bit %= mod;
        }
        printf("Case #%d: %lld\n", ++kase, tot);
    }
    return 0;
}

6.Function(HDU6038)

题目链接

题意:问有多少种函数,满足条件 f(i)=bf(ai) ,两个函数不一样,条件是两个函数又要给f(i)的值不一样。

思路:首先我们可以观察到a和b中都存在着循环节,所以

f(i)=bf(ai)=bbf(aai)=bbf(i)l times b 其中l是i所在a中循环节的长度

要想满足这个条件,b中循环节长度要是a中循环节长度的因数才可以。

如果f(i)的值确定下来,则当前长度l的f值也都知道了。

所以起始最后求的答案其实就是将a中所有循环节的答案数相乘

每一个长度为l的循环节的答案是 j|lj 就相当于用一个j的循环节循环填充了一个了一个l 的,然后将这个结果乘k次k是a中长度为l的循环节的个数,然后将每一种长度的循环节乘在一起就是结果了。

最终的答案通式是:
i=1k(j|lijcalbj)calai

其中 kacalaiaicalbjbjliaijba

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define pi acos(-1)
#define maxn 111111
#define maxm 11111
#define INF 0x3F3F3F3F
#define eps 1e-8

#define pb push_back

#define mem(a) memset(a,0,sizeof a)

using namespace std;

const long long mod = 1000000007;
/**lyc**/
void init() {

}
int n, m;
int a[maxn][2]; //0是a,1是b
int cal[maxn][2]; //0是a,1是b cal[i]为长度为i的循环节有多少个。
bool vis[maxn];
void dfs(int x, int l, int op) {
    if(vis[x]) {
        cal[l][op]++;
        return;
    }
    vis[x] = 1;
    dfs(a[x][op], l + 1, op);
}
int main() {
    int kase = 0;
    while(scanf("%d%d", &n, &m) != EOF) {
        memset(cal, 0, sizeof cal);
        for(int i = 0; i < n; i++) {
            scanf("%d", &a[i][0]);
        }
        for(int i = 0; i < m; i++) {
            scanf("%d", &a[i][1]);
        }
        memset(vis, 0, sizeof vis);
        for(int i = 0; i < n; i++) if(!vis[i]) {
            dfs(i, 0, 0);
        }
        memset(vis, 0, sizeof vis);
        for(int i = 0; i < m; i++) if(!vis[i]) {
            dfs(i, 0, 1);
        }
        long long ans = 1LL;
        for(int i = 1; i <= n; i++) if(cal[i][0]) {
            long long tot = 0;
            int limt = (int)sqrt(i + 0.5);
            for(int j = 1; j <= limt; j++) {
                if(i % j == 0) {
                    tot += 1LL * cal[j][1] * j % mod;
                    tot %= mod;
                    if(i != j * j) {
                        tot += 1LL * cal[i / j][1] * (i / j) % mod;
                        tot %= mod;
                    }
                }
            }
            for(int j = 1; j <= cal[i][0]; j++) {
                ans = (ans * tot) % mod;
            }
        }
        printf("Case #%d: %lld\n", ++kase, ans);
    }
    return 0;
}

8.Hints of sd0061

题目链接

题意:找出每个测试对应的新手,对于每个测试有一个b_i对于每一个新手有一个a_k,每个测试b_i的人需要一个a_k 值倒数第(b_i + 1)

思路:将b_i值排一个序,每次求出当前区间的第b_i大的值,然后用类似模拟快排的方法求,这里我学习了一个标程给的函数nth_element

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define pi acos(-1)
#define maxn 111111
#define maxm 11111
#define INF 0x3F3F3F3F
#define eps 1e-8

#define pb push_back

#define mem(a) memset(a,0,sizeof a)

using namespace std;

const long long mod = 1000000007;
/**lyc**/
int n, m, A, B, C;
unsigned a[10001111];
int b[111];
int pos[111];
unsigned ans[111];
unsigned x, y, z;
inline
unsigned rng61() {
  unsigned t;
  x ^= x << 16;
  x ^= x >> 5;
  x ^= x << 1;
  t = x;
  x = y;
  y = z;
  z = t ^ x ^ y;
  return z;
}
bool cmp(int x, int y) {
    return b[x] < b[y];
}
int main() {
    int kase = 0;

    while(scanf("%d%d%d%d%d", &n, &m, &A, &B, &C) != EOF) {
        for(int i = 0; i < m; i++) {
            scanf("%d", &b[i]);
            pos[i] = i;
        }
        sort(pos, pos + m, cmp);
        pos[m] = m;
        b[m] = n;
        x = A, y = B, z = C;
        for(int i = 0; i < n; i++) {
            a[i] = rng61();
        }
        for(int i = m - 1; i >= 0; i--) {
            if(i != m - 1 && b[pos[i]] == b[pos[i + 1]]) { ///省下b相同的计算
                ans[pos[i]] = ans[pos[i + 1]];
                continue;
            }
            nth_element(a, a + b[pos[i]], a + b[pos[i + 1]]);
            ///将a数组中这个0-b[pos[i + 1]]-1这个范围里第b[pos[i]]大的数放在第b[pos[i]]-1的位置上
            ans[pos[i]] = a[b[pos[i]]];
        }
        printf("Case #%d:", ++kase);
        for(int i = 0; i < m; i++)
            printf(" %u", ans[i]);
        printf("\n");
    }
    return 0;
}

你可能感兴趣的:(多校)