A 美丽的2
【问题描述】
小蓝特别喜欢2,今年是公元2020年,他特别高兴。
他很好奇,在公元1年到公元2020年(包含)中,有多少个年份的数位中包含数字2?
#include <iostream>
#include <cstdio>
using namespace std;
int main(){
int sum=0,n=2020;
for(int i=1;i<=n;i++){
int year=i;
while(year>0){
if(year%10==2){
sum++;
break;
}
year/=10;
}
}
printf("%d\n",sum);
return 0;
}
答案:563
B:扩散
【问题描述】
小蓝在一张无限大的特殊画布上作画。
这张画布可以看成一个方格图,每个格子可以用一个二维的整数坐标表示。小蓝在画布上首先点了一下几个点:(0,0),(2020,11),(11,14),(2000,2000)。只有这几个格子上有黑色,其它位置都是白色的。
每过一分钟,黑色就会扩散一点。具体的,如果一个格子里面是黑色,它就会扩散到上、下、左、右四个相邻的格子中,使得这四个格子也变成黑色(如果原来就是黑色,则还是黑色)。
请问,经过2020分钟后,画布上有多少个格子是黑色的。
#include <iostream>
#include <cstdio>
using namespace std;
//(0,0),(2020,11),(11,14),(2000,2000)
int main() {
long long sum = 0;
for (int i = -5000; i <= 5000; i++) {
for (int j = -5000; j <= 5000; j++) {
if (((abs(i-0)+abs(j-0))<=2020)||((abs(i-2020)+abs(j-11))<=2020)||((abs(i-11)+abs(j-14))<=2020)||((abs(i-2000)+abs(j-2000))<=2020)) {
sum++;
}
}
}
printf("%lld\n", sum);
return 0;
}
答案: 20312088
C阶层约数
【问题描述】
定义阶乘n!=1×2×3×··×n。
请问100! (100的阶乘)有多少个约数。
例如:10的质数乘积=25 ,约数个数=(1+1)(1+1)=4;如上所说1 2 5 10
180的质数乘积=2x2x3x3x5,约数个数=(2+1)(2+1)(1+1)=18。约数为
1 2 3 4 5 6 9 10 12 15 18 20 30 36 45 60 90 180 。
a1,a2,a3就是分解质因数出现的个数(幂数),180分解后=2^2 + 2^3 + 5^1。
#include <iostream>
#include <cstdio>
using namespace std;
int arr[105];
int main() {
//记录结果
long long sum=1;
for (int i = 2; i <= 100; i++) {
//将每个数分解质因数,即将这个数分为质数乘积组成的形式,记录分解的数出现次数。
int j = 2, i1 = i;
while (i1 != j) {
if (i1 % j == 0) {
arr[j]++;
i1 = i1 / j;
} else {
j++;
}
}
//最后i1==j就是分解到最后一个质数,将这个质数记录
arr[j]++;
}
//根据公式,约数个数=(a1+1)*(a2+1)*(an+1)...a就是质因数出现次数(幂数)
for (int i=2; i<=100; i++) {
if (arr[i]!=0)
sum*=(arr[i]+1);
}
//输出结果
cout << sum << endl;
return 0;
}
#include <iostream>
using namespace std;
int p[100];
int main()
{
for (int i = 2; i <= 100; i ++)
{
int n = i;
for (int j = 2; j <= n / j; j ++)
while(n % j == 0)
{
p[j] ++;
n /= j;
}
if(n > 1) p[n] ++;
}
long long ans = 1;
for (int i = 2; i <= 100; i ++)
if(p[i]) ans *= (p[i] + 1);
cout << ans << endl;
return 0;
}
答案: 39001250856960000
D:本质上升序列
【问题描述】
小蓝特别喜欢单调递增的事物。
在一个字符串中,如果取出若干个字符,将这些字符按照在字符串中的顺序排列后是单调递增的,则成为这个字符串中的一个单调递增子序列。
例如,在字符串 lanqiao 中,如果取出字符n和 q,则nq组成一个单调递增子序列。类似的单调递增子序列还有lnq、 i、 ano 等等。
小蓝发现,有些子序列虽然位置不同,但是字符序列是一样的,例如取第二个字符和最后一个字符可以取到 ao,取最后两个字符也可以取到ao。小蓝认为他们并没有本质不同。
对于一个字符串,小蓝想知道,本质不同的递增子序列有多少个?
例如,对于字符串 lanqiao,本质不同的递增子序列有21个。它们分别是l、a、n、q、 i、o、ln、an、lq、aq、nq、ai、lo、ao、no、io、lnq、anq、 lno、 ano、 aio。
请问对于以下字符串(共200个小写英文字母,分四行显示):(如果你把以下文字复制到文本文件中,请务必检查复制的内容是否与文档中的一致。在试题目录下有一个文件 inc.txt,内容与下面的文本相同>
tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhfiadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqijgihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmadvrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkghfwl
本质不同的递增子序列有多少个?
在这里插入代码片
E:玩具蛇
小蓝有一条玩具蛇,一共有16 节,上面标着数字1 至16。每一节都是一个正方形的形状。相邻的两节可以成直线或者成90 度角。
小蓝还有一个4 X 4 的方格盒子,用于存放玩具蛇,盒子的方格上依次标着字母A 到P 共16 个字母。
小蓝可以折叠自己的玩具蛇放到盒子里面。他发现,有很多种方案可以将玩具蛇放进去。
下图给出了两种方案:
请帮小蓝计算一下,总共有多少种不同的方案。如果两个方案中,存在玩具蛇的某一节放在了盒子的不同格子里,则认为是不同的方案。
#include <iostream>
#include <cstring>
using namespace std;
int vis[7][7] = {0};
long long ans = 0;
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
void dfs(int x, int y, int step) {
if (vis[x][y]==1) {
return;
}
if (step == 16) {
ans++;
return;
}
vis[x][y] = 1;
for (int it = 0; it < 4; it++) {
if (vis[x + dx[it]][y + dy[it]] == 0 &&
1 <= x + dx[it] && x + dx[it] <= 4 &&
1 <= y + dy[it] && y + dy[it] <= 4) {
dfs(x + dx[it], y + dy[it], step + 1);
}
}
vis[x][y] = 0;
}
int main() {
for (int i = 1; i <= 4; i++) {
for (int j = 1; j <= 4; j++) {
memset(vis, 0, sizeof(vis));
dfs(i, j, 1);
}
}
cout << ans;
return 0;
}
答案: 552
F: 皮亚诺曲线距离
G: 游园安排
链接: 原文地址
方法一:动态规划+回溯(70%)
//方法一:动态规划+回溯
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1e6+10;
int num;
string s;
int f[N]; //按照顺序存储
string v[N];//存储分割人名
int main() {
string s;
cin>>s;
//s="WoAiLanQiaoBei";
for (int i=0; i<s.length(); i++) { //分割字符串
if (s[i]>='A'&&s[i]<='Z') {
num++;
v[num]="";
v[num]+=s[i];
} else {
v[num]+=s[i];
}
}
int max1=0;//最长字典长度(人名的个数)
max1=0;//开始数组长度为空
int pos=1;
for (int i=1; i<=num; i++) {
f[i]=1;
for (int j=1; j<i; j++) { //查找后边的人名
if (v[j]<v[i]) {
f[i]=max(f[i], f[j]+1);
}
}
if (f[i]>=max1) {
max1=f[i];
pos=i;
}
}
string res="";
for (int i=pos; i>=1; i--) {
if (f[i]==max1) {
res=v[i]+res;
max1--;
}
}
cout<<res<<endl;
return 0;
}
方法二:动态规划优化-二分加贪心(100%)
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int num;
string s;
string v[N];
vector<string> endd;
vector<int> f;
int main()
{
cin>>s;
for(int i=0;i<s.length();i++)
{
if(s[i]>='A'&&s[i]<='Z')
{
if(i!=0)
num++;
v[num]="";
v[num]+=s[i];
}
else
{
v[num]+=s[i];
}
}
endd.push_back(v[0]);
f.push_back(1);
for(int i=1;i<=num;i++) //遍历到最后一个子字符串数组元素
{
if(v[i]>endd.back()) //如果当前end中的字符串能构成上升序列
{
endd.push_back(v[i]); //则将当前子字符串入队
f.push_back(endd.size()); //那么当前动态数组的长度就是当前上升序列的长度
}
else
{ //下面是贪心做法
//如果不能构成单调上升序列
int pos=lower_bound(endd.begin(),endd.end(),v[i])-endd.begin();
//找到大于等于序列v[i]的第一个元素的位置
endd[pos]=v[i]; //将这个元素替换为v[i](这个可能不好理解,下面会说的)
f.push_back(pos+1);
//更新一下,那么当前的上升序列的长度就是pos+1(因为0-pos是单调上升的,加上0这个首元素所以是pos+1)
}
}
string k[N]; //用字符串连接会超时
int cnt=0;
for(int i=num,m=endd.size();m>0;i--) //类似动态规划将结果逆序输出
{
if(f[i]==m)
{
k[cnt++]=v[i];
m--;
}
}
for(int i=cnt-1;i>=0;i--) cout<<k[i];
return 0;
}
H: 答疑
在这里插入代码片
I: 出租车
J: 质数行者