2017 Multi-University Training Contest 1

1001

题意:求2的m次方减去一这个数的位数

思路:很显然只有100 - 1, 1000 - 1 这类数减去1之后位数会降,2的m次方位数不可能是0,所以对m * log10(2)向下取整即可

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <map>
#include <set>
#include <vector>
#include <utility>
#include <queue>
#include <stack>
#include <string>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9;
const int qq = 2e5 + 10;
const double eps = 1e-9;
int dp[qq];

int main(){
	LL n, Cas = 0;
	while(scanf("%lld", &n) != EOF) {
		printf("Case #%lld: ", ++Cas);
		double ans = log10(2.) / log10(10.);
		LL t = floor(n * ans);
		printf("%lld\n", t);
	}
	return 0;
}


1002

题意:给出n个字符串,对于字符a~z,赋值0~25,求在26进制下的最大值

思路:num[i][j]记录第i位上字符j有多少个,然后化成26进制,相当于比较字符a~z的26进制数的大小,然后贪心即可。

但是注意这里字符不能有前导零但是可以有字符串0,比如一个数据

26

a

b

c

...

z

那么其中必定有一个字符会被赋值为0,也就成了字符串0,但是其他情况不允许出现前导零,所以这种情况需要特判一下,然后对最小那个字符并且不在前导情况下赋值0

其他情况就是正常情况了

调了比较久,代码写的很...>..<

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <map>
#include <set>
#include <vector>
#include <utility>
#include <queue>
#include <stack>
#include <string>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b)    memset(a, b, sizeof a)
#define REP(i, x, n)    for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e5 + 50;
int n;
LL num[qq][30], cp[qq][26];
int maxn[30], ct[30], cpmaxn[30];
char st[qq];

bool cmp(int x, int y) {
    if(maxn[x] == maxn[y]) {
        for(int i = maxn[x]; i >= 0; --i) {
            if(num[i][x] == num[i][y])    continue;
            return num[i][x] < num[i][y];
        }    
    }
    return maxn[x] < maxn[y];
}
bool vis[30], isapp[30];

int main(){
    int Cas = 0;
    while(scanf("%d", &n) != EOF) {
        mst(num, 0), mst(maxn, 0), mst(vis, false), mst(isapp, false);
        printf("Case #%d: ", ++Cas);
        for(int i = 0; i < n; ++i) {
            scanf("%s", st);
            int len = strlen(st);
            if(len > 1) vis[st[0] - 'a'] = true;
            for(int j = len - 1, k = 0; j >= 0; --j, k++) {
                num[k][st[j] - 'a']++;
                isapp[st[j] - 'a'] = true;
                maxn[st[j] - 'a'] = max(maxn[st[j] - 'a'], k);
            }
        }
        for(int i = 0; i < 26; ++i) {
            cpmaxn[i] = maxn[i];
            for(int j = 0; j <= maxn[i]; ++j) {
                cp[j][i] = num[j][i];
            }
        }
        for(int i = 0; i < 26; ++i) {
            LL t = 0;
            for(int j = 0; j <= maxn[i]; ++j) {
                LL tmp = (num[j][i] + t) / 26;
                num[j][i] = (t + num[j][i]) % 26;
                t = tmp;
                if(tmp > 0) {
                    maxn[i] = max(maxn[i], j + 1);
                }
            }
        }
        for(int i = 0; i < 26; ++i) {
            ct[i] = i;
        }
        int cnt = 0;
        for(int i = 0; i < 26; ++i) {
            if(isapp[i])    cnt++;
        }
        sort(ct, ct + 26, cmp);
        int id = -1;
        if(cnt == 26) {
            for(int i = 0; i < 26; ++i) {
                if(vis[ct[i]] == false) {
                    id = i;
                    break;
                }
            }
        }
        LL tmp = 0;
        LL k = 25;
        for(int i = 25; i >= 0; --i) {
            if(id == i) {
                continue;
            }
            LL ans = 0;
            for(int j = cpmaxn[ct[i]]; j >= 0; --j) {
//                printf("%c %lld\n", ct[i] + 'a', cp[j][ct[i]]);
                ans = (ans * 26LL) % MOD;
                ans = (ans + ((cp[j][ct[i]] * k) % MOD + MOD)) % MOD;
            }
            k = k - 1;
            tmp = ((tmp + ans) % MOD + MOD) % MOD;
        }
        printf("%lld\n", tmp);
    }
    return 0;
}


1006

参考:传送门

关键要想到构成了这种循环节

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <map>
#include <set>
#include <vector>
#include <utility>
#include <queue>
#include <stack>
#include <string>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9;
const int qq = 1e5 + 10;
int n, m;
int a[qq], b[qq];
LL num1[qq], num2[qq];
void Init() {
	mst(num1, 0);
	mst(num2, 0);
}

int main(){
	int Cas = 0;
	while(scanf("%d%d", &n, &m) != EOF) {
		Init();
		for(int i = 0; i < n; ++i) {
			scanf("%d", a + i);
		}
		for(int i = 0; i < m; ++i ){
			scanf("%d", b + i);
		}
		int cycle = 0;
		for(int i = 0; i < n; ++i) {
			LL tot = 0;
			int k = i;
			while(a[k] != -1) {
				tot++;
				int t = k;
				k = a[k];
				a[t] = -1;
			}
			if(tot)	num1[++cycle] = tot;
		}
//		puts("111");
		for(int i = 0; i < m; ++i) {
			LL tot = 0;
			int k = i;
			while(b[k] != -1) {
				tot++;
				int t = k;
				k = b[k];
				b[t] = -1;
			}
			if(tot)	num2[tot]++;
		}
//		puts("111");
		LL ans = 1;
		for(int i = 1; i <= cycle; ++i) {
			LL ansl = 0;
			for(int j = 1; j * j <= num1[i]; ++j) {
				if(num1[i] % j == 0) {
					if(j * j == num1[i]) {
						ansl += num2[j] * j;
					} else {
						ansl += num2[j] * j + num2[num1[i] / j] * (num1[i] / j);
					}
				}
			}
			ans = (ans * ansl) % MOD;
		}
//		puts("111");
		printf("Case #%d: %lld\n", ++Cas, ans);
	}
	return 0;
}

1011

题意:n双袜子放在橱柜里数字标号1~n,每天在橱柜拿一双袜子并且是当前数字最小的,当天晚上会把袜子扔进楼子里,当楼子里的袜子积累到n - 1双的时候,主人公会洗并且在第二天的晚上放进橱柜里,问第k天用的是那双袜子

思路:很显然k小于等于n时,答案就是k,k大于n是也知道前n次的结果,那么在第n天你用n这个袜子,之后n - 1天你可以用1 ~ n-1编号的袜子,那么在n + n - 1天你用的是n - 1这双袜子,之后n - 1天你可以用 1 ~ n - 2, n这袜子,规律很显然。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <map>
#include <set>
#include <vector>
#include <utility>
#include <queue>
#include <stack>
#include <string>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int MOD = 1e9;
const int qq = 2e5 + 10;

int main(){
	LL n, m;
	int Cas = 0;
	while(scanf("%lld%lld", &n, &m) != EOF) {
		printf("Case #%d: ", ++Cas);
		if(n >= m) {
			printf("%lld\n", m);
		} else {
			m = m - n;
			LL tmp = m / (n - 1);
			LL t = n % (n - 1);
			if(t == 0) {
				printf("%lld\n", tmp % 2 == 1 ? n - 1 : n);
			} else {
				printf("%lld\n", t);
			}
		}
 	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值