Codeforces 379D - New Year Letter
原题地址:http://codeforces.com/contest/379/problem/D
题目大意:给出一种生成字符串的方法 s[k] = s[k - 2] + s[k - 1],其中加法意为将左右两个字符串直接相连,要求构造两个长度分别为n、m的字串s[1]、s[2],使得按照这种方法得出的s[k]中恰好含有 x 个 “AC”(意思大家都懂的……)如果无解,输出“Happy new year!”
数据范围:3 ≤ k ≤ 50; 0 ≤ x ≤ 109; 1 ≤ n, m ≤ 100
题目分析:
这道题算法很明确。
先将问题反过来思考:假设给定两个串s[1]、s[2],用题目中的方法生成s[k],求出s[k]含有几个“AC”,显然可以用动态规划解决
定义f[k]表示第k个串中含有“AC”的个数,Suf[k]为第 k 个串的结尾字母,Pre[k]为第k个串的开头字母,三个数组的1、2两位都是已知的
显然可以得到动态规划方程 f[k] = f[k - 2] + f[k - 1] + (Suf[k - 2] == 'A') && (Pre[k - 1] == 'C'); Suf[k] = Suf[k - 1]; Pre[k] = Pre[k - 2]
然后搞一搞就得到答案了。那么我们回归这道题,发现可以通过枚举f[1]、f[2]、Suf[1]、Suf[2]、Pre[1]、Pre[2]来DP计算所有可能的f[k],如果找到一组f[1]、f[2]、Suf[1]、Suf[2]、Pre[1]、Pre[2]使得f[k] == x,就按照它们构造两个字符串输出就好了
复杂度分析:每次枚举Pre[1]等等都是三种情况(是A、是C、不是A也不是C),一共枚举4轮,枚举f[1]时不可能超过二分之n,枚举f[2]时也同理,所以枚举的总复杂度是O(3 * 3 * (m / 2) * 3 * 3 * (n / 2))大约为202500,每次DP都是线性的所以复杂度是O(k)所以总复杂度可以约归为O(nmk)大概在10^7左右勉强不会超时。
剩下的就是细节了,这道题一大堆特殊情况需要判断(比如n , m <= 2啦什么的),详见代码~
//date 20140120
#include <cstdio>
#include <cstring> inline int min(int a, int b){return a < b ? a : b;}
inline int max(int a, int b){return a > b ? a : b;} int k, n, m;
long long x;
long long f[];
int suf[], pre[]; void dp(int w)
{
if(w <= )return;
if(f[w - ] == -)dp(w - );
if(f[w - ] == -)dp(w - );
f[w] = f[w - ] + f[w - ] + ((suf[w - ] == ) && (pre[w - ] == ));
suf[w] = suf[w - ]; pre[w] = pre[w - ];
} inline void output(int S1, int S2, int P1, int P2, int i, int j)
{
// printf("%d %d %d %d %d %d\n", S1, P1, i, S2, P2, j);
char ans1[], ans2[];
memset(ans1, , sizeof ans1);
memset(ans2, , sizeof ans2);
ans1[] = P1 + 'A' - ;
ans2[] = P2 + 'A' - ;
ans1[n] = S1 + 'A' - ;
ans2[m] = S2 + 'A' - ;
// printf("%s\n%s\n", ans1 + 1, ans2 + 1); int a1 = , a2 = ;
if(i > && ans1[] == 'A')
{
ans1[] = 'C';a1 = ;
for(int q = ; q < i; ++q){ans1[q * + ] = 'A'; ans1[q * + ] = 'C'; a1 = q * + ;}
for(int q = a1; q < n; ++q)ans1[q] = 'B';
}
else
{
a1 = ;
for(int q = ; q <= i; ++q){ans1[q * ] = 'A'; ans1[q * + ] = 'C'; a1 = q * + ;}
for(int q = a1; q < n; ++q)ans1[q] = 'B';
}
if(j > && ans2[] == 'A')
{
ans2[] = 'C'; a2 = ;
for(int q = ; q < j; ++q){ans2[q * + ] = 'A'; ans2[q * + ] = 'C'; a2 = q * + ;}
for(int q = a2; q < m; ++q)ans2[q] = 'B';
}
else
{
a2 = ;
for(int q = ; q <= j; ++q){ans2[q * ] = 'A'; ans2[q * + ] = 'C'; a2 = q * + ;}
for(int q = a2; q < m; ++q)ans2[q] = 'B';
}
printf("%s\n%s\n", ans1 + , ans2 + );
} int main()
{
// freopen("d.in", "r", stdin); scanf("%d%I64d%d%d", &k, &x, &n, &m); for(int P1 = ; P1 <= ; ++P1)
for(int S1 = ; S1 <= ; ++S1)
for(int P2 = ; P2 <= ; ++P2)
for(int S2 = ; S2 <= ; ++S2)
{
if(n == && S1 != P1)continue;
if(m == && S2 != P2)continue;
int uLim1 = , uLim2 = , dLim1 = , dLim2 = ;
uLim1 = max(n / - , ); if((n >= ) && ((S1 == && P1 == ) || ((n & ) && (S1 == || P1 == ))))++uLim1;
uLim2 = max(m / - , ); if((m >= ) && ((S2 == && P2 == ) || ((m & ) && (S2 == || P2 == ))))++uLim2;
if(n == && S1 == && P1 == )dLim1 = uLim1 = ;
if(m == && S2 == && P2 == )dLim2 = uLim2 = ;
// printf("%d %d %d %d\n", dLim1, uLim1, dLim2, uLim2);
for(int i = dLim1; i <= uLim1; ++i)
for(int j = dLim2; j <= uLim2; ++j)
{
memset(suf, , sizeof suf);
memset(pre, , sizeof pre);
suf[] = S1; suf[] = S2;
pre[] = P1; pre[] = P2;
memset(f, 0xFF, sizeof f);
f[] = i; f[] = j;
dp(k);
// printf("%d %d %d %d %d %d %d\n", P1, S1, P2, S2, i, j, f[k]);
if(f[k] == x){output(S1, S2, P1, P2, i, j); return ;}
}
} printf("Happy new year!\n");
return ;
}
小注:希望通过这道题能给我和大家带来更多的新年AC~
Codeforces 379D - New Year Letter的更多相关文章
- codeforces Good Bye 2013 379D New Year Letter
题目链接:http://codeforces.com/problemset/problem/379/D [题目大意] 告诉你初始字符串S1.S2的长度和递推次数k, 使用类似斐波纳契数列的字符串合并的 ...
- 【codeforces 379D】New Year Letter
[题目链接]:http://codeforces.com/contest/379/problem/D [题意] 让你构造出两个长度分别为n和m的字符串s[1]和s[2] 然后按照连接的规则,顺序连接s ...
- CodeForces 379D 暴力 枚举
D. New Year Letter time limit per test 1 second memory limit per test 256 megabytes input standard i ...
- Codeforces Round #284 (Div. 2)A B C 模拟 数学
A. Watching a movie time limit per test 1 second memory limit per test 256 megabytes input standard ...
- cf499B-Lecture 【map】
http://codeforces.com/problemset/problem/499/B B. Lecture You have a new professor of graph theo ...
- 物联网学生科协第三届H-star现场编程比赛
问题 A: 剪纸片 时间限制: 1 Sec 内存限制: 128 MB 题目描写叙述 这是一道简单的题目,假如你身边有一张纸.一把剪刀.在H-star的比赛现场,你会这么做: 1. 将这张纸剪成两片(平 ...
- Codeforces Round #116 (Div. 2, ACM-ICPC Rules) C. Letter 暴力
C. Letter Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/180/problem/C D ...
- Codeforces Beta Round #14 (Div. 2) A. Letter 水题
A. Letter 题目连接: http://www.codeforces.com/contest/14/problem/A Description A boy Bob likes to draw. ...
- CodeForces 379 D. New Year Letter
枚举开头结尾的字母,枚举ac的个数,总AC个数就是两个Fibonacci数列的和..... D. New Year Letter time limit per test 1 second memory ...
随机推荐
- C# 数组CopyTo
private void button1_Click(object sender, RoutedEventArgs e) { int[] copy1 = { 1, 2, 3, 4 }; int[] c ...
- How to use Android Activity's finish(), onDestory() and System.exit(0) methods
Activity.finish() Calling this method will let the system know that the programmer wants the current ...
- 2877: [Noi2012]魔幻棋盘 - BZOJ
DescriptionInput 第一行为两个正整数N,M,表示棋盘的大小. 第二行为两个正整数X,Y,表示棋盘守护者的位置. 第三行仅有一个正整数T,表示棋盘守护者将进行次操作. 接下来N行,每行有 ...
- IntelliJ IDEA 15 显示工具栏及底部周边工具栏
- SQL Server 之 校对
_CI(CS) 是否区分大小写,CI不区分,CS区分 _AI(AS) 是否区分重音,AI不区分,AS区分 _KI(KS) 是否区分假名类型,KI不区分,KS区分 _WI(WS) 是否区分宽度 WI不区 ...
- Memcache安全配置
Memcache安全配置 瞌睡龙 · 2014/01/20 17:59 0x00 Memcache简介 Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash ...
- Proxmox虚拟机增加硬盘容量
1.首先在虚拟机控制台选择调整硬盘容量,弹出窗口为增加的容量 2.重启虚拟机,用fdisk –l查看新增容量是否被识别 3.用cfdisk创建分区,分区格式为Primary 8e (Linux LVM ...
- tornado解析http body的过程分析
tornado解析http body的过程分析 在最近写的一个RESTful API Server过程中,发现tornaod对解析POST BODY的内容有限制. 而在以前用web.py则没有这个限制 ...
- 【面试题012】打印1到最大的n位数
[面试题012]打印1到最大的n位数 大数问题 字符串中的每一个字符都是‘0’到‘9’之间的某一个字符,用来表示数字中的一位,因为数字最大是n位的,因此我们需要一个长度为n+1的字符串,字符串的最后 ...
- TopCoder 603 div1 & div2
div2 250pts MiddleCode 题意:s串长度为奇数时,将中间字符取掉并添加到t末尾:长度为偶数时,将中间两个较小的字符取掉并添加到末尾. 分析:直接做,学习了一下substr(s, p ...