@Dmaxiya
2018-08-17T10:27:50.000000Z
字数 5086
阅读 1001
Codeforces
Contests 链接:Codeforces Round #309 (Div. 2)
过题数:3
排名:143/9399
给定一个由小写字母组成的字符串 ,可以在字符串的任意位置插入一个字符,从而生成一个新的字符串,问能够生成的不同的新字符串的个数。
在字符串的每个位置暴力插入,放入 中统计即可。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <functional>
#include <iomanip>
using namespace std;
#define LL long long
string str;
set<string> st;
int main() {
#ifdef LOCAL
freopen("test.txt", "r", stdin);
// freopen("test1.out", "w", stdout);
#endif // LOCAL
ios::sync_with_stdio(false);
while(cin >> str) {
st.clear();
int len = str.length();
for(int i = 0; i <= len; ++i) {
for(char ch = 'a'; ch <= 'z'; ++ch) {
st.insert(str.substr(0, i) + ch + str.substr(i, len - i));
}
}
cout << st.size() << endl;
}
return 0;
}
给定一个 的 矩阵,每次操作可以将任意一列的所有 翻转为 , 翻转为 ,问最多可以使多少行变为全 。
由于每次翻转是按列翻转,所以对于一种固定的列的翻转,要使 行变为全 ,这 行的 位置必须完全相同,即这些串必须相等,所以用 统计每种字符串的个数,求最大的字符串出现个数就是答案。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <functional>
#include <iomanip>
using namespace std;
#define LL long long
int n, ans;
string str;
map<string, int> mp;
int main() {
#ifdef LOCAL
freopen("test.txt", "r", stdin);
// freopen("test1.out", "w", stdout);
#endif // LOCAL
ios::sync_with_stdio(false);
while(cin >> n) {
mp.clear();
ans = 0;
for(int i = 0; i < n; ++i) {
cin >> str;
++mp[str];
ans = max(ans, (int)mp[str]);
}
cout << ans << endl;
}
return 0;
}
有 个球,每个球有一种颜色,总共有 种颜色,颜色编号为 ,第 种颜色的球的个数为 。现在 将这些球都放入袋子中,依次从袋子中抽球,问第 种颜色的最后一个抽出来的球,比第 种颜色的最后一个被抽出的球早抽出的总的方案数有多少种,输出方案对 取模后的结果。
题目要算的其实是排列的方案数,我们可以通过这种方式生成合法的排列:将第 到第 种颜色的球依次放入排列中,在放第 种颜色的球时,先将一个球放在最后的位置,剩下的 个球就可以任意插入到前 个球的排列中,这就相当于计算在 个球中插入 个隔板的方案数,方案数为:。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <functional>
#include <iomanip>
using namespace std;
#define LL long long
const LL MOD = 1000000007;
const int maxn = 1000000 + 100;
int n;
LL fac[maxn];
LL num[maxn], sum[maxn];
void exgcd(LL a, LL b, LL &d, LL &x, LL &y) {
if(b == 0) {
d = a;
x = 1;
y = 0;
} else {
exgcd(b, a % b, d, y, x);
y -= x * (a / b);
}
}
LL inv(LL n) {
LL x, y, d;
exgcd(n, MOD, d, x, y);
x = (x % MOD + MOD) % MOD;
return x;
}
int main() {
#ifdef LOCAL
freopen("test.txt", "r", stdin);
// freopen("test1.out", "w", stdout);
#endif // LOCAL
ios::sync_with_stdio(false);
fac[0] = 1;
for(int i = 1; i < maxn; ++i) {
fac[i] = fac[i - 1] * i % MOD;
}
while(scanf("%d", &n) != EOF) {
for(int i = 1; i <= n; ++i) {
scanf("%I64d", &num[i]);
sum[i] = sum[i - 1] + num[i];
}
LL ans = 1;
for(int i = 1; i <= n; ++i) {
ans = ((ans * (fac[sum[i] - 1] * inv(fac[sum[i - 1]]) % MOD) % MOD) * inv(fac[num[i] - 1])) % MOD;
}
printf("%I64d\n", ans);
}
return 0;
}
对于一个给定的 的排列,可以通过值 下标找到许多个环,例如:序列 ,可以找到环 ,在每个环内,将数字按从大到小排序,再以每个环为整体,按字典序排序,可以得到:,得到新的序列 ,对于某些特殊的序列,通过这样的变换后仍是它自己。给定 ,找到 的全排列中,满足以上关系的第 小的排列。
,其中 表示所有满足条件的排列数。
首先通过打一个 的表可以找到以下满足条件的排列:
可以发现,这些满足条件的排列,相比于排列 只有相邻两个数字之间存在交换,我们将交换的两个数字标为 ,其他位标为 ,可以产生下面的序列:
箭头右边的数字表示交换位置的数字的最高位(假设右边为最低位,且下标从 开始),可以发现,数字 对应的序列的最高两位都为 ,最低两位与数字 对应的序列的最低两位相同,数字 对应的序列的最高两位都为 ,最低三位与数字 对应的序列的最低三位相同,再往后推(将 扩大到 或者更大)可以发现,数字 对应的序列的最高两位总是 ,最低 位与数字 到 对应的序列的最低 位相同,如果我们将 记为数字 对应的序列个数,令 ,则 ,这正好是一个斐波那契数列,因此可以对斐波那契数列进行二分查找,找到需要交换的最高位的位置,交换后将 减去 ,继续二分查找,直到 。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <algorithm>
#include <functional>
#include <iomanip>
using namespace std;
typedef long long LL;
const int maxn = 100 + 100;
int n, cnt;
LL k;
int ans[maxn];
LL fib[maxn];
LL *it;
int main() {
#ifdef LOCAL
freopen("test.txt", "r", stdin);
// freopen("test1.out", "w", stdout);
#endif // LOCAL
ios::sync_with_stdio(false);
fib[0] = 1;
fib[1] = 1;
for(int i = 2; i < maxn; ++i) {
fib[i] = fib[i - 1] + fib[i - 2];
if(fib[i] > 1000000000000000000LL) {
cnt = i;
break;
}
}
while(scanf("%d%I64d", &n, &k) != EOF) {
for(int i = 1; i <= n; ++i) {
ans[i] = i;
}
while(k > 1) {
it = lower_bound(fib, fib + cnt, k);
int pos = n - (it - fib) + 1;
swap(ans[pos], ans[pos + 1]);
--it;
k -= *it;
}
for(int i = 1; i <= n; ++i) {
if(i != 1) {
printf(" ");
}
printf("%d", ans[i]);
}
printf("\n");
}
return 0;
}