HDOJ1297
第一次做这道题的时候,以为就是一个简单的递推题,但还是too native,结果自然是WA,后来测试发现题目给的范围是1~1000,但是取100数据就会溢出(即便使用的是long long),因此需要使用大数计算。
先简单的分析这题的递推公式:用f(n)表示排队种类,假定已知f(n-1)
第n个是男生,则有f(n-1)种可能
第n个是女生,首先需要明确要使f(n)要合法,那么第n-1个必须为女生,接着需要分类讨论,如果前n-2个学生排列合法,则有f(n-2)种可能,如果前n-2个学生不合法,即第n-2是女生,第n-3是男生,此时再加上两个女生,队列就变成合法,因此这种情况有f(n-4)种可能
该题递推公式为f(n)=f(n-1)+f(n-2)+f(n-4)
接着需要解决大数计算的问题,接下来再引入ACM1002
大数计算基本思路:利用字符数组来保存每一位上的数字,并模拟手算
先讲解大数计算的核心代码:
定义两个数组,用来存储需要相加的两个数
1 |
|
程序做循环相加的时候要知道什么时候退出,因此需要知道较长的字符串长度,作为退出标志
1 | int len1,len2,max_len; |
接下来我们要模拟手算
1 | int temp=0; //用来保存临时结算结果 |
贴上杭电ACM1002的代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using namespace std;
void add(char num1[MAXN], char num2[MAXN])
{
int temp1[MAXN] = { 0 };int temp2[MAXN] = { 0 };
int len1 = 0;int len2 = 0;
int i = 0, j = 0;
int maxlen = 0;
len1 = strlen(num1);
len2 = strlen(num2);
////反转字符串,便于从低位到高位相加和最高位的进位导致和的位数增加
for (i = len1 - 1; i >= 0; i--)
{
temp1[j++] = num1[i] - '0';
}
temp1[j] = '\0';
j = 0;
for (i = len2 - 1; i >= 0; i--)
{
temp2[j++] = num2[i] - '0';
}
//一位一位的加
maxlen = (len1 > len2) ? len1 : len2;
for (i = 0; i < maxlen; i++) {
temp1[i] += temp2[i];
if (temp1[i] >= 10) {
temp1[i] -= 10;
temp1[i + 1]++;
}
}
for (i = maxlen - 1; i >= 0; i--)
cout << temp1[i];
}
int main()
{
char s1[MAXN]; char s2[MAXN];
/*gets_s(num1);
gets_s(num2);*/
int t;
cin >> t;
for (int j = 1; j <= t;j++) {
cin >> s1 >>s2;
cout << "Case " << j << ":" << endl;
cout << s1 << " + " << s2<<" = ";
add(s1, s2);
cout << endl;
if (j!= t) {
cout << endl;
}
}
//add(num1, num2);
return 0;
}