比赛A了B, G,H,I, 赛后我独自整理了F,J, 还有A题貌似可以做,可惜没时间,下次再整理吧。
讲一下J和F的思路, 还有贴J和K的代码
J :其实就是把字母映射分成元音和辅音两组就可以了, 那么我们暴力dfs把26个字母分成2组的状态,然后根据输入的串相邻位置不能是同一组的把一大堆无用状态删去,然后找到一个有用的就停,修改一下即可。
注意:每个单词有可能用空行隔开。
F:数位统计题吧,我们先预处理出dp,cnt数组
// dp[x] x位为1的所有数的个数
// cnt[x] x位为1的所有数的1的个数
那么我们可以先让x从小到大把能减的减去,得到第n个位置在长度len的二进制数上,那么
将len-1位置1,多次从后往前扫一遍,每扫一遍就要将有些位置1,一直到结束,具体看代码吧,
细节很多,我还写了暴力程序对拍。
code J:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
char str[100005], s[100005];
bool g[33][33];
char yuan[] = {"AEUOI"};
char fu[] = {"BCDFGHJKLMNPQRSTVWXYZ"};
char idx[256];
void go(char *t) {
int i;
int len = strlen(t);
for(i = 0; i < len-1; i++) {
if(t[i] >= 'A' && t[i] <= 'Z' && t[i+1] >= 'A' && t[i+1] <= 'Z') {
g[t[i]-'A'][t[i+1]-'A'] = true;
}
}
}
int pos, st;
bool dfs(int pos, int cnt, int st) {
if(pos == 26) {
if(cnt != 5) return false;
bool ok = true;
for(int x = 0; x < 26 && ok; x++)
for(int y = 0; y < 26 && ok; y++)
if(g[x][y] && (((st>>x)&1)^((st>>y)&1)^1)) {
ok = false;
}
if(ok) {
::st = st;
return true;
}
return false;
}
if(cnt < 5)
if(dfs(pos+1, cnt+1, st<<1|1)) return true;
if(dfs(pos+1, cnt, st<<1)) return true;
return false;
}
int main() {
freopen("javanese.in", "r", stdin);
freopen("javanese.out", "w", stdout);
int i;
memset(g, false, sizeof(g));
while(gets(str) && str[0] != 't') {
go(str);
int len = strlen(str);
for(i = 0; i < len; i++)
s[pos++] = str[i];
s[pos++] = '\n';
}
if(!dfs(0, 0, 0)) return cout<<"impossible"<<endl, 0;
int idy = 0, idf = 0;
// puts("~~~~~~~~`");
for(i = 0; i < 26; i++) {
if(st&(1<<i)) idx[i+'A'] = yuan[idy++];
else idx[i+'A'] = fu[idf++];
}
// for(i = 0; i < 26; i++)
// printf("%c->%c\n", i+'A', idx[i+'A']);
int len = strlen(s);
// printf("len = %d\n",len);
for(i = 0; i < len; i++)
if(s[i] >= 'A' && s[i] <= 'Z') {
s[i] = idx[s[i]];
// printf("%c %c\n", s[i], idx[s[i]]);
}
for(i = 0; i < len; i++)
printf("%c", s[i]);
puts("");
return 0;
}
/*
A->B
B->C
C->D
D->F
E->G
F->H
G->J
H->K
I->L
J->M
K->N
L->O
M->P
N->Q
O->R
P->S
Q->T
R->V
S->W
T->X
U->Y
V->A
W->E
X->U
Y->O
Z->I
*/
code F:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
ll duipai[100005];
void debug() { //暴力对拍
int i, j;
string str;
for(i = 1; i <= 10000; i++) {
j = i;
string tp;
while(j > 0) {
tp += j % 2 + '0';
j >>= 1;
}
reverse(tp.begin(), tp.end());
bool flag = false;
for(j = 0; j < (int) tp.size() - 1; j++)
if(tp[j] == tp[j + 1] && tp[j] == '1') {
flag = true;
break;
}
if(!flag) {
str += tp;
}
}
for(i = 1; i <= 1000; i++)
duipai[i] = duipai[i - 1] + (str[i - 1] == '1');
}
int num[222];
int cal(int len, int x) {
int ret = 0;
for(int i = 0; i < x; i++) {
ret += num[len-i];
}
return ret;
}
ll dp[100005], cnt[100005], n;
// dp[x] x位为1的所有数的个数
// cnt[x] x位为1的所有数的1的个数
int main() {
freopen("fibonacci.in", "r", stdin);
freopen("fibonacci.out", "w", stdout);
int i;
cnt[0] = 0;
cnt[1] = 1;
dp[0] = 1;
dp[1] = 1;
ll s1 = 0, s2 = 1;
for(i = 2; i <= 100000; i++) {
cnt[i] = s1 + s2;
s1 += cnt[i - 1];
dp[i] = s2;
s2 += dp[i - 1];
}
//debug();
while(cin >> n) {
if(!n) {
cout << "0" << endl;
continue;
}
ll ans = 0;
for(i = 1;; i++) {
if(n >= dp[i] * i) {
n -= dp[i] * i;
ans += cnt[i];
}
else break;
}
int len = i;
memset(num, 0, sizeof(num));
num[len-1] = 1;
if(n <= len) {
ans += cal(len-1, n);
cout << ans << endl;
continue;
}
int pre = 1, pos = len - 2;
while(true) {
for(i = 0; i <= pos; i++) {
if(n >= dp[i] * len) {
n -= dp[i] * len;
ans += cnt[i] + pre * dp[i];
}
else break;
}
num[i-1] = 1;
if(n <= len) {
ans += cal(len-1, n);
break;
}
else pos = i - 2;
pre++;
}
cout << ans << endl;
}
return 0;
}