2017 Multi-University Training Contest - Team 1训练总结(持续更新中)

Add More Zero

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
There is a youngster known for amateur propositions concerning several mathematical hard problems.

Nowadays, he is preparing a thought-provoking problem on a specific type of supercomputer which has ability to support calculations of integers between  0  and  (2m1)  (inclusive).

As a young man born with ten fingers, he loves the powers of  10  so much, which results in his eccentricity that he always ranges integers he would like to use from  1 to  10k  (inclusive).

For the sake of processing, all integers he would use possibly in this interesting problem ought to be as computable as this supercomputer could.

Given the positive integer  m , your task is to determine maximum possible integer  k  that is suitable for the specific supercomputer.
 

Input
The input contains multiple test cases. Each test case in one line contains only one positive integer  m , satisfying  1m105 .
 

Output
For each test case, output " Case # x y " in one line (without quotes), where  x  indicates the case number starting from  1  and  y  denotes the answer of corresponding case.
 

Sample Input
  
  
1 64
 

Sample Output
  
  
Case #1: 0 Case #2: 19
 

Statistic |  Submit |  Clarifications |  Back



题意:问2^m-1有几位...

思路:你会发现-1只有在 10的倍数时候位数才会发生变化 10-1 = 9, 100-1, 1000-1...2^m不可能出现这种数

,所以只考虑2^m有几位就好了...就是10的几次方, 取个log10, 答案就是m×log2;

代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
int main()
{
    int n, ca = 1;
    while(~scanf("%d", &n))
    {
        int k = log10(2)*n;
        printf("Case #%d: %d\n",ca++, k);
    }
    return 0;
}

Balala Power!

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description

Talented  Mr.Tang has  n  strings consisting of only lower case characters. He wants to charge them with Balala Power (he could change each character ranged from  a to  z into each number ranged from  0 to  25, but each two different characters should not be changed into the same number) so that he could calculate the sum of these strings as integers in base  26  hilariously.

Mr.Tang wants you to maximize the summation. Notice that no string in this problem could have leading zeros except for string "0". It is guaranteed that at least one character does not appear at the beginning of any string.

The summation may be quite large, so you should output it in modulo  109+7 .
 

Input
The input contains multiple test cases.

For each test case, the first line contains one positive integers  n , the number of strings.  (1n100000)

Each of the next  n  lines contains a string  si  consisting of only lower case letters.  (1|si|100000,|si|106)
 

Output
For each test case, output " Case # x y " in one line (without quotes), where  x  indicates the case number starting from  1  and  y  denotes the answer of corresponding case.
 

Sample Input
  
  
1 a 2 aa bb 3 a ba abc
 

Sample Output
  
  
Case #1: 25 Case #2: 1323 Case #3: 18221
 

Statistic |  Submit |  Clarifications |  Back

题意:给你n个由小写字母组成的字符串,让你给26个字母分配0-25,每个字符串形成一个26进制的数字,问怎么分

权值这n个数的和最大。(不能有前导0,但是单个0可以)


官方题解:每个字符对答案的贡献都可以看作一个 26 进制的数字,问题相当于要给这些贡献加一个 0 到 25 的权重

使得答案最大。最大的数匹配 25,次大的数匹配 24,依次类推。排序后这样依次贪心即可,唯一注意的是不能出现

前导 0。关键就是排序,其实结构体排序可以按照数组字典序排序的

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 1e5+5;
ll fac[maxn] = {1};
int tmp[27];
int Hash[27];
bool lead[27];
char str[maxn];

void init()
{
    for(int i = 1; i < maxn; i++)
        fac[i] = fac[i-1]*26%mod;
}

struct node
{
    int cnt[maxn];
    int id;
    bool operator < (const node &a) const
    {
        for(int i = maxn-1; i >= 0; i--)
        {
            if(cnt[i] > a.cnt[i]) return 1;
            else if(cnt[i] < a.cnt[i]) return 0;
            else ;
        }
    }
}a[27];

int main(void)
{
    int n, ca = 1;
    init();
    while(~scanf("%d", &n))
    {
        memset(a, 0, sizeof(a));
        memset(Hash, -1, sizeof(Hash));
        memset(lead, 0, sizeof(lead));
        int r = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf(" %s", str);
            int len = strlen(str);
            r = max(r, len-1);
            if(len != 1)
                lead[str[0]-'a'] = 1;
            for(int i = 0; i < len; i++)
                a[str[i]-'a'].cnt[len-i-1]++;
        }
        for(int i = 0; i < 26; i++)
        {
            for(int j = 0; j < maxn; j++)
            {
                if(a[i].cnt[j] >= 26)
                {
                    a[i].cnt[j+1] += a[i].cnt[j]/26;
                    a[i].cnt[j] %= 26;
                }
            }
            a[i].id = i;
        }
        sort(a, a+26);
//        for(int i = 0; i < 26; i++)
//            cout << a[i].id << endl;
        for(int i = 0; i < 26; i++)
            Hash[a[i].id] = 26-i-1;
        for(int i = 0; i < 26; i++)
            if(lead[a[i].id] && Hash[a[i].id] == 0)
            {
                for(int j = 25; j >= 0; j--)
                {
                    if(!lead[a[j].id])
                    {
                        for(int k = 25; k >= j+1; k--)
                            Hash[a[k].id] = Hash[a[k-1].id];
                        Hash[a[j].id] = 0;
//                        swap(Hash[a[i].id], Hash[a[j].id]);
                        break;
                    }
                }
                break;
            }
        ll ans = 0;
//        for(int i = 0; i < 26; i++)
//            cout << Hash[i] << endl;
        for(int i = 0; i < 26; i++)
        {
            for(int j = 0; j < maxn; j++)
            {
                ans = (ans+fac[j]*a[i].cnt[j]*Hash[a[i].id]%mod)%mod;
            }
        }
        printf("Case #%d: %lld\n", ca++, ans);
    }
    return 0;
}


Function

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 300    Accepted Submission(s): 114


Problem Description
You are given a permutation  a  from  0  to  n1  and a permutation  b  from  0  to  m1 .

Define that the domain of function  f  is the set of integers from  0  to  n1 , and the range of it is the set of integers from  0  to  m1 .

Please calculate the quantity of different functions  f  satisfying that  f(i)=bf(ai)  for each  i  from  0  to  n1 .

Two functions are different if and only if there exists at least one integer from  0  to  n1  mapped into different integers in these two functions.

The answer may be too large, so please output it in modulo  109+7 .
 

Input
The input contains multiple test cases.

For each case:

The first line contains two numbers  n,   m (1n100000,1m100000)

The second line contains  n  numbers, ranged from  0  to  n1 , the  i -th number of which represents  ai1 .

The third line contains  m  numbers, ranged from  0  to  m1 , the  i -th number of which represents  bi1 .

It is guaranteed that  n106,   m106 .
 

Output
For each test case, output " Case # x y " in one line (without quotes), where  x  indicates the case number starting from  1  and  y  denotes the answer of corresponding case.
 

Sample Input
  
  
3 2 1 0 2 0 1 3 4 2 0 1 0 2 3 1
 

Sample Output
  
  
Case #1: 4 Case #2: 4
 

Source
 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:   6044  6043  6042  6041  6040 

题目大意:


给你一个数组A,和一个数组B,数组A是【0~n-1】的排咧,数组B是【0~m-1】的排列。

现在定义F(i)=bF(ai);

问有多少种取值,使得F(i)全部合法。

样例1可行的解:

110

111

001

000


思路:


写出样例2的公式:


①F(0)=bF(2)

②F(1)=bF(0)

③F(2)=bF(1)


我们不难发现,如果我们设定了F(0)的值,就能够通过式子②能够得知F(1)的值,然后就能通过式子③得知F(2)的值,最后再回归式子①尝试当前设定的值是否合法了。


这就是一个循环节


我们对于A数组中的一个环的话如果一个环中的任意一个点的价值我们能够设定出来,那么这一个循环节的所有点的值就都能够知道了。

然而这个能够设定的值,肯定是数组B中的一个值,而且我们已知都是循环节,那么数组B中的这个被选中设定的值也一定存在一个循环节,而且这个循环节的长度,一定是A长度循环节的因子长度。


A数组中长度为D的一个循环节,如果B数组中有一个循环节的长度为d,并且如果D%d==0.那么这个B数组的这个循环节的所有值,都可以作为A数组中这个循环节的值。那么对于A数组中的这个循环节来讲,答案数就多了d个。

过程统计每个循环节能够满足的答案的个数,然后累乘即可。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 7;
const int Mod = 1e9 + 7;
int a[maxn], b[maxn], n, m, cnt1[maxn], cnt2[maxn], book[maxn];
int main()
{
    int ca = 1;
    while(~scanf("%d%d", &n, &m))
    {
        memset(cnt1, 0, sizeof(cnt1));
        memset(cnt2, 0, sizeof(cnt2));
        for(int i = 0; i < n; i++)
            scanf("%d", &a[i]);
        for(int i = 0; i < m; i++)
            scanf("%d", &b[i]);
        memset(book, 0, sizeof(book));
        int tot = 0;
        for(int i = 0; i < n; i++)
        {
            int index = i, cnt = 0;
            while(!book[index])
            {
                cnt++;
                book[index] = 1;
                index = a[index];
            }
            if(cnt)
                cnt1[tot++] = cnt;
        }
        memset(book, 0, sizeof(book));
        for(int i = 0; i < m; i++)
        {
            int index = i, cnt = 0;
            while(!book[index])
            {
                cnt++;
                book[index] = 1;
                index = b[index];
            }
            if(cnt)
                cnt2[cnt]++;
        }
        ll ans = 1;
        for(int i = 0; i < tot; i++)
        {
            ll tmp = 0;
            for(int j = 1; j * j <= cnt1[i]; j++)
            {
                if(cnt1[i]%j == 0)
                {
                    if(j*j == cnt1[i])
                        tmp += cnt2[j]*j;
                    else
                        tmp += cnt2[j]*j + cnt2[cnt1[i]/j]*cnt1[i]/j;
                }
            }
                ans = ans*tmp%Mod;
        }
        printf("Case #%d: %lld\n",ca++, ans);
    }
    return 0;
}

KazaQ's Socks

水..

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll n, k;
int main(void)
{
    int ca = 1;
    while(~scanf("%lld%lld", &n ,&k))
    {
        printf("Case #%d: ", ca++);
        if(k <= n)
        {
            printf("%lld\n", k);
            continue;
        }
        k -= n;
        k %= (2*n-2);
        if(k == 0)
        {
            printf("%lld\n", n);
            continue;
        }
        if(k <= n-1)
            printf("%lld\n", k);
        else
            printf("%lld\n", k%(n-1));
    }
    return 0;
}
转自:http://blog.csdn.net/qq_28954601/article/details/76177586

Description

sd0061, the legend of Beihang University ACM-ICPC Team, retired last year leaving a group of noobs. Noobs have no idea how to deal with m coming contests. sd0061 has left a set of hints for them.

There are n noobs in the team, the i-th of which has a rating ai. sd0061 prepares one hint for each contest. The hint for the j-th contest is a number bj, which means that the noob with the (bj+1)-th lowest rating is ordained by sd0061 for the j-th contest.

The coach asks constroy to make a list of contestants. constroy looks into these hints and finds out: bi+bj≤bk is satisfied if bi≠bj, bi

Input

There are multiple test cases (about 10).

For each test case:

The first line contains five integers n,m,A,B,C. (1≤n≤10^7,1≤m≤100)

The second line contains m integers, the i-th of which is the number bi of the i-th hint. (0≤bi

Output

For each test case, output “Case #x: y1 y2 ⋯ ym” in one line (without quotes), where x indicates the case number starting from 1 and yi (1≤i≤m) denotes the rating of noob for the i-th contest of corresponding case.

 

Sample Input

3 3 1 1 1
0 1 2
2 2 2 2 2
1 1

 

Sample Output

Case #1: 1 1 202755
Case #2: 405510 405510

 

题意

用题中所给的函数生成 n 个数,然后有 m 次查询,查询数列  a  中第  bi  大的数是多少。

 

思路

​如果单纯想着排序以后直接输出的话会超时,因为 n 最大有  107  ,也就是数列的长度最大也是这些。

那么就应该想想其他线性的解法了, STL 库中实现了 nth_element 函数,其功能是使第 n 大元素处于第 n 个位置,并且比这个元素小的元素都排在它之前,比这个元素大的元素都排在它之后,但不能保证它们是有序的。

template<class RandomAccessIterator>  
void nth_element(RandomAccessIterator first, RandomAccessIterator nth, RandomAccessIterator last);  
 
 
  • 1
  • 2
  • 1
  • 2

时间复杂度:平均为线性。

然后在使用过程中做一点点的优化就可以了,题中有说  bi+bjbk  ,因此我们在查询时从大往小开始遍历,这样每次都可以减掉数组的一半长度。

#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;

unsigned x, y, z;

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;
}

typedef pair<int,int> P;
const int manx = 1e7+10;
unsigned a[manx];
unsigned ans[manx];
P b[110];

int main()
{
    ios::sync_with_stdio(false);
    int n,m,kase=0;
    while(cin>>n>>m>>x>>y>>z)
    {
        for(int i=0; i<m; i++)
        {
            cin>>b[i].first;
            b[i].second=i;
        }
        for(int i=0; i<n; i++)
            a[i]=rng61();
        sort(b,b+m);
        b[m].first=n;
        for(int i=m-1; i>=0; i--)
        {
            nth_element(a,a+b[i].first,a+b[i+1].first);
            ans[b[i].second]=a[b[i].first];
        }
        cout<<"Case #"<<++kase<<":";
        for(int i=0; i<m; i++)
            cout<<" "<<ans[i];
        cout<<endl;
    }
    return 0;
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值