Problem 16 Power digit sum
思路
高精度乘法,这里用了万进制数,可以少一些循环
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1000 + 10;
int work(int x, int n) {
int dig[N];
int k = 1;
dig[0] = 1;
for(int i = 0; i < n; i++) {
int carry = 0;
for(int j = 0; j < k; j++) {
carry += dig[j] * x;
dig[j] = carry % 10000;
carry /= 10000;
}
if(carry) {
dig[k++] = carry;
}
}
int ans = 0;
for(int i = 0; i < k; i++) {
while(dig[i] != 0) {
ans += dig[i] % 10;
dig[i] /= 10;
}
}
return ans;
}
int main() {
printf("%d\n", work(2, 1000));
return 0;
}
Problem 17 Number letter counts
#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
map<int, string> mp;
void init() {
mp[1] = "one";
mp[2] = "two";
mp[3] = "three";
mp[4] = "four";
mp[5] = "five";
mp[6] = "six";
mp[7] = "seven";
mp[8] = "eight";
mp[9] = "nine";
mp[10] = "ten";
mp[11] = "eleven";
mp[12] = "twelve";
mp[13] = "thirteen";
mp[14] = "fourteen";
mp[15] = "fifteen";
mp[16] = "sixteen";
mp[17] = "seventeen";
mp[18] = "eighteen";
mp[19] = "nineteen";
mp[20] = "twenty";
mp[30] = "thirty";
mp[40] = "forty";
mp[50] = "fifty";
mp[60] = "sixty";
mp[70] = "seventy";
mp[80] = "eighty";
mp[90] = "ninety";
mp[100] = "hundred";
mp[1000] = "thousand";
}
int work(int n) {
int ans = 0;
for(int i = 1; i <= n; i++) {
int val = i;
if(val >= 1000) {
ans += mp[val/1000].size() + mp[1000].size();
if(val % 1000 != 0) {
ans += 3;
}
val %= 1000;
}
if(val >= 100) {
ans += mp[val/100].size() + mp[100].size();
if(val % 100 != 0) {
ans += 3;
}
val %= 100;
}
if(val >= 20) {
ans += mp[val-val%10].size();
val %= 10;
}
if(val != 0) {
ans += mp[val].size();
}
}
return ans;
}
int main() {
init();
printf("%d\n", work(1000));
return 0;
}
Problem 18 Maximum path sum I
思路
动态规划,从上向下转移的话,状态转移方程 d p [ i ] [ j ] + = m a x ( d p [ i − 1 ] [ j − 1 ] , d p [ i − 1 ] [ j ] ) dp[i][j] += max(dp[i-1][j-1], dp[i-1][j]) dp[i][j]+=max(dp[i−1][j−1],dp[i−1][j]),最终取最后一层中最大的值即可。当然也可以从下向上转移
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 50;
int work(int dp[][N], int n) {
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= i; j++) {
dp[i][j] += max(dp[i-1][j-1], dp[i-1][j]);
}
}
int ans = 0;
for(int i = 1; i <= n; i++) {
ans = max(ans, dp[n][i]);
}
return ans;
}
int main() {
int n = 15;
int dp[N][N];
memset(dp, 0, sizeof(dp));
for(int i = 1; i <= 15; i++) {
for(int j = 1; j <= i; j++) {
scanf("%d", &dp[i][j]);
}
}
printf("%d\n", work(dp, n));
return 0;
}
Problem 19 Counting Sundays
#include <iostream>
#include <cstdio>
using namespace std;
bool isLeap(int n) {
return n%400 == 0 || (n%4==0 && n%100 != 0);
}
int work() {
int month[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int ans = 0, day = 1;
for(int i = 1900; i <= 2000; i++) {
for(int j = 1; j <= 12; j++) {
if(i >= 1901 && day == 0) {
++ans;
}
if(j == 2) {
day = (day + (isLeap(i) ? 29 : 28)) % 7;
} else {
day = (day + month[j]) % 7;
}
}
}
return ans;
}
int main() {
printf("%d\n", work());
return 0;
}
Problem 20 Factorial digit sum
思路
高精度乘法,这里用了万进制数
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1000;
int work(int n) {
int dig[N];
int k = 1;
dig[0] = 1;
for(int i = 1; i <= n; i++) {
int carry = 0;
for(int j = 0; j < k; j++) {
carry += dig[j] * i;
dig[j] = carry % 10000;
carry /= 10000;
}
if(carry) {
dig[k++] = carry;
}
}
int ans = 0;
for(int i = 0; i < k; i++) {
while(dig[i] != 0) {
ans += dig[i] % 10;
dig[i] /= 10;
}
}
return ans;
}
int main() {
int n = 100;
printf("%d\n", work(n));
return 0;
}