先存个样~~之后补全
个人解法,可能不是最佳,欢迎指错
小总结,第一次参加总得来一个国二,(但我还是很菜)
下面是自己习惯性用的头文件
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<vector>
#include<cmath>
#define pii pair<int,int>
#define mem(kk,i) memset(kk,i,sizeof kk)
using namespace std;
typedef long long ll;
const int maxn=1e7;
const int INF=0x3f3f3f3f;
/*next_permutation();
prev_permutation():
*/
A:美丽的 2
【问题描述】
小蓝特别喜欢 2,今年是公元 2020 年,他特别高兴。
他很好奇,在公元 1 年到公元 2020 年(包含)中,有多少个年份的数位中包含数字 2?
思路:直接1-2020枚举判断
int main(){
int tot=0;
for(int i=1;i<=2020;i++){
int k=i;
while(k){
int g=k%10;
k/=10;
if(g==2){tot++;break;}
}
}
cout<<tot<<endl;
return 0;
}
答案:563
B:扩散
【题目描述】
小蓝在一张无限大的特殊画布上作画。
这张画布可以看成一个方格图,每个格子可以用一个二维的整数坐标表示。
小蓝在画布上首先点了一下几个点:(0, 0), (2020, 11), (11, 14), (2000, 2000)。
只有这几个格子上有黑色,其它位置都是白色的。
每过一分钟,黑色就会扩散一点。具体的,如果一个格子里面是黑色,它就会扩散到上、下、左、右四个相邻的格子中,使得这四个格子也变成黑色(如果原来就是黑色,则还是黑色)。
请问,经过 2020 分钟后,画布上有多少个格子是黑色的。
思路:bfs跑,,然后时间在2020内都记录,边记录边累计个数,每个加个2100,从0开始,一分钟向上扩散1,最多不超过2100
struct node{
int x;
int y;
int t;
};
int da[4][2]={1,0,-1,0,0,-1,0,1};
int n=2100;
int ma[10000][10000],vis[10000][10000];
queue<node> q;
void bfs(){
mem(ma,0);
mem(vis,0);
node s,p;
p.t=0,p.x=n,p.y=n;q.push(p);
p.t=0,p.x=n+2000,p.y=n+2000;q.push(p);
p.t=0,p.x=n+2020,p.y=n+11;q.push(p);
p.t=0,p.x=n+11,p.y=n+14;q.push(p);
vis[n][n]=vis[n+2000][n+2000]=vis[n+2020][n+11]=vis[n+11][n+14]=1;
ll ans=4;
while(!q.empty()){
p=q.front();
q.pop();
for(int i=0;i<4;i++){
s.x=p.x+da[i][0];
s.y=p.y+da[i][1];
s.t=p.t+1;
if(vis[s.x][s.y]==0&&s.t<=2020){
vis[s.x][s.y]=1;
ans++;
q.push(s);
}
}
}
cout<<ans<<endl;
}
int main(){
bfs();
return 0;
}
答案:20312088
C阶层约数
【问题描述】
定义阶乘 n! = 1 × 2 × 3 × · · · × n。
请问 100! (100 的阶乘)有多少个约数。
思路:将它的每个因数分解,比如 5! = 1x2x3x4x5 = 23x31x51,
2就可以挑选0个、1个、2个、3个,同样3和5,那他的约数个数就是每个约数指数的乘积,相当于多少种方法
这个是看了这个博主
(当时差一点就想到了,没做出来,哎,可惜吖!)
代码:
int a[101];
int main(){
mem(a,0);
for(int i=2;i<=100;i++){
int tem=i;
for(int j=2;j<=i;j++){
while(tem%j==0){
tem/=j;
a[j]++;
}
}
}
ll ans=1;
for(int i=1;i<=100;i++)
ans*=(a[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,内容与下面的文本相同)
tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhfiadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqijgihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmadvrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl
本质不同的递增子序列有多少个?
思路:计算每个子序列,我先转化成数字了
代码:
ull ma[250],dp[250];
int main(){
mem(dp,0);
for(int i=0;i<250;i++)dp[i]=1;
string ch;
cin>>ch;
cout<<ch.length()<<endl;
for(int i=0;i<ch.length();i++){
ma[i]=ch[i]-'a';
}
for(int i=0;i<ch.length();i++){
for(int j=0;j<i;j++){
if(ma[i]>ma[j])dp[i]+=dp[j];
}
}
ull ans=0;
for(int i=0;i<ch.length();i++){
ans+=dp[i];
}
cout<<ans<<endl;
return 0;
}
答案:2472673705(怎么感觉错了,好多人是:3616159)
E: 玩具蛇
【问题描述】
小蓝有一条玩具蛇,一共有 16 节,上面标着数字 1 至 16。每一节都是一个正方形的形状。相邻的两节可以成直线或者成 90 度角。
小蓝还有一个 4 × 4 的方格盒子,用于存放玩具蛇,盒子的方格上依次标着字母 A 到 P 共 16 个字母。
小蓝可以折叠自己的玩具蛇放到盒子里面。他发现,有很多种方案可以将玩具蛇放进去。
下图给出了两种方案:
请帮小蓝计算一下,总共有多少种不同的方案,如果两个方案中,卒年在玩具蛇的某一节放在盒子的不同格子里,则认为是不同的方案数。
思路:dfs各个找一遍,实话说,这题好像比前面简单。。
ll tot=0,n=4;
int ma[5][5];
int da[4][2]={-1,0,1,0,0,-1,0,1};
void dfs(int i,int j,int k){
if(!ma[i][j]&&k==n*n){
tot++;
return ;
}
ma[i][j]=k;
for(int e=0;e<4;e++){
int dx=i+da[e][0];
int dy=j+da[e][1];
if(dx>=1&&dy>=1&&dy<=n&&dx<=n&&!ma[dx][dy]){
dfs(dx,dy,k+1);
}
}
ma[i][j]=0;
}
int main(){
mem(ma,0);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
dfs(i,j,1);
cout<<tot<<endl;
}
cout<<tot<<endl;
return 0;
}
答案:552
F: 皮亚诺曲线距离
【问题描述】
皮亚诺曲线是一条平面内的曲线。
下图给出了皮亚诺曲线的 1 阶情形,它是从左下角出发,经过一个 3 × 3 的方格中的每一个格子,最终到达右上角的一条曲线。
下图给出了皮亚诺曲线的 2 阶情形,它是经过一个 32 × 32 的方格中的每一个格子的一条曲线。它是将 1 阶曲线的每个方格由 1 阶曲线替换而成。

下图给出了皮亚诺曲线的 3 阶情形,它是经过一个 33 × 33 的方格中的每一个格子的一条曲线。它是将 2 阶曲线的每个方格由 1 阶曲线替换而成。
皮亚诺曲线总是从左下角开始出发,最终到达右上角。
我们将这些格子放到坐标系中,对于 k 阶皮亚诺曲线,左下角的坐标是(0, 0),右上角坐标是 (3k − 1, 3k − 1),右下角坐标是 (3k − 1, 0),左上角坐标是(0, 3k − 1)。
给定 k 阶皮亚诺曲线上的两个点的坐标,请问这两个点之间,如果沿着皮亚诺曲线走,距离是多少?
【输入格式】
输入的第一行包含一个正整数 k,皮亚诺曲线的阶数。第二行包含两个整数 x1, y1,表示第一个点的坐标。
第三行包含两个整数 x2, y2,表示第二个点的坐标。
【输出格式】
输出一个整数,表示给定的两个点之间的距离。
【样例输入】
1
0 0
2 2
【样例输出】
8
【样例输入】
2
0 2
0 3
【样例输出】
13
【评测用例规模与约定】
对于 30% 的评测用例,0 ≤ k ≤ 10。
对于 50% 的评测用例,0 ≤ k ≤ 20。
对于所有评测用例,0 ≤ k ≤ 100, 0 ≤ x1, y1, x2, y2 < 3k, x1, y1, x2, y2 ≤ 1018。
数据保证答案不超过 1018。
代码:没写出来。。
G: 游园安排
【问题描述】
L 星球游乐园非常有趣,吸引着各个星球的游客前来游玩。小蓝是 L 星球游乐园的管理员。
为了更好的管理游乐园,游乐园要求所有的游客提前预约,小蓝能看到系统上所有预约游客的名字。每个游客的名字由一个大写英文字母开始,后面跟0 个或多个小写英文字母。游客可能重名。
小蓝特别喜欢递增的事物。今天,他决定在所有预约的游客中,选择一部分游客在上午游玩,其他的游客都在下午游玩,在上午游玩的游客要求按照预约的顺序排列后,名字是单调递增的,即排在前面的名字严格小于排在后面的名字。
一个名字 A 小于另一个名字 B 是指:存在一个整数 i,使得 A 的前 i 个字母与 B 的前 i 个字母相同,且 A 的第 i+1 个字母小于 B 的第 i+1 个字母。(如果 A 不存在第 i + 1 个字母且 B 存在第 i + 1 个字母,也视为 A 的第 i + 1 个字母小于 B 的第 i + 1 个字母)
作为小蓝的助手,你要按照小蓝的想法安排游客,同时你又希望上午有尽量多的游客游玩,请告诉小蓝让哪些游客上午游玩。如果方案有多种,请输出上午游玩的第一个游客名字最小的方案。如果此时还有多种方案,请输出第一个游客名字最小的前提下第二个游客名字最小的方案。如果仍然有多种,依此类推选择第三个、第四个……游客名字最小的方案。
【输入格式】
输入包含一个字符串,按预约的顺序给出所有游客的名字,相邻的游客名字之间没有字符分隔。
【输出格式】
按预约顺序输出上午游玩的游客名单,中间不加任何分隔字符。
【样例输入】
WoAiLanQiaoBei
【样例输出】
AiLanQiao
【评测用例规模与约定】
对于 20% 的评测数据,输入的总长度不超过 20 个字母。
对于 50% 的评测数据,输入的总长度不超过 300 个字母。
对于 70% 的评测数据,输入的总长度不超过 10000 个字母。
对于所有评测数据,每个名字的长度不超过 10 个字母,输入的总长度不超
过 1000000 个字母。
思路:排个顺序,比较字母个数,小字母多的放前面,一样多的,小字母靠前放前面
(不敢保证完全对)代码:
string x[1000001];
bool cmp(const string a,const string b){
int visa[30],visb[30];
mem(visa,0);
mem(visb,0);
visa[a[0]-'A']++;
visb[b[0]-'A']++;
for(int i=1;i<a.length();i++)
visa[a[i]-'a']++;
for(int i=1;i<b.length();i++)
visb[b[i]-'a']++;
int mn=min(a.length(),b.length());
for(int i=0;i<mn;i++){
if(visa[i]>visb[i])return 1;
else if(visa[i]<visb[i])return 0;
}
if(a.length()>b.length())return 0;
else if(a.length()<b.length()) return 1;
else{
for(int i=0;i<mn;i++)
if(a[i]>b[i])return 0;
else if(a[i]<b[i])return 1;
return 1;
}
}
int main(){
int n=-1;
string ch;
cin>>ch;
int i=0;
while(i<=ch.length()){
if(ch[i]>='A'&&ch[i]<='Z'){
n++;
x[n]+=(ch[i]);
}
else if(ch[i]!='\0') x[n]+=ch[i];
i++;
}
n++;
sort(x,x+n,cmp);
for(int i=0;i<=n/2;i++)cout<<x[i];
cout<<endl;
return 0;
}
H: 答疑
【问题描述】
有 n 位同学同时找老师答疑。每位同学都预先估计了自己答疑的时间。老师可以安排答疑的顺序,同学们要依次进入老师办公室答疑。
一位同学答疑的过程如下:
首先进入办公室,编号为 i 的同学需要 si 毫秒的时间。
然后同学问问题老师解答,编号为 i 的同学需要 ai 毫秒的时间。
答疑完成后,同学很高兴,会在课程群里面发一条消息,需要的时间可 以忽略。
最后同学收拾东西离开办公室,需要 ei 毫秒的时间。一般需要 10 秒、20 秒或 30 秒,即 ei 取值为 10000,20000 或 30000。
一位同学离开办公室后,紧接着下一位同学就可以进入办公室了。
答疑从 0 时刻开始。老师想合理的安排答疑的顺序,使得同学们在课程群里面发消息的时刻之和最小。
【输入格式】
输入第一行包含一个整数 n,表示同学的数量。
接下来 n 行,描述每位同学的时间。其中第 i 行包含三个整数 si, ai, ei,意义如上所述。
【输出格式】
输出一个整数,表示同学们在课程群里面发消息的时刻之和最小是多少。
【样例输入】
3
10000 10000 10000
20000 50000 20000
30000 20000 30000
【样例输出】
280000
【样例说明】
按照 1, 3, 2 的顺序答疑,发消息的时间分别是 20000, 80000, 180000。
【评测用例规模与约定】
对于 30% 的评测用例,1 ≤ n ≤ 20。
对于 60% 的评测用例,1 ≤ n ≤ 200。
对于所有评测用例,1 ≤ n ≤ 1000,1 ≤ si ≤ 60000,1 ≤ ai ≤ 1000000,ei ∈ {10000, 20000, 30000},即 ei 一定是 10000、20000、30000 之一。
思路:s+e+a小的放前面,一样的就把s+a小的放前面
(不保证完全对)代码:
struct student{
ll s,a,e;
};
student stu[1001];
bool cmp(const student n1,const student n2){
/*ll sum1=n1.a+n1.e+n1.s+n2.a+n2.s;
ll sum2=n2.a+n2.e+n2.s+n1.a+n1.s;
if(sum1==sum2)return n1.a+n1.s<n2.a+n2.s;
return sum1<sum2;
*/
ll sum1=n1.s+n1.a,sum2=n2.s+n2.a;
if(sum1+n1.e>sum2+n2.e)return 0;
else if(sum1+n1.e<sum2+n2.e)return 1;
else{
if(sum1>sum2)return 0;
else if(sum1<sum2)return 1;
else return 1;
}
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>stu[i].s>>stu[i].a>>stu[i].e;
}
sort(stu,stu+n,cmp);
ll ans=0,k=0;
for(int i=0;i<n;i++){
//cout<<stu[i].s<<" "<<stu[i].a<<" "<<stu[i].e<<endl;
k=k+stu[i].s+stu[i].a;
ans+=k;
//cout<<k<<endl;
k+=stu[i].e;
}
cout<<ans<<endl;
return 0;
}
I: 出租车
问题描述】
小蓝在 L 市开出租车。
L 市的规划很规整,所有的路都是正东西向或者正南北向的,道路都可以看成直线段。东西向的道路互相平行,南北向的道路互相平行,任何一条东西向道路垂直于任何一条南北向道路。
从北到南一共有 n 条东西向道路,依次标号为 H 1 , H 2 , ···, H n 。从西到东一共有 m 条南北向的道路,依次标号为 S 1 , S 2 , ···, S m 。
每条道路都有足够长,每一条东西向道路和每一条南北向道路都相交,H i与 S j 的交叉路口记为 (i, j)。
从 H 1 和 S 1 的交叉路口 (1,1) 开始,向南遇到的路口与 (1,1) 的距离分别
是 h 1 , h 2 , ···, h n−1 ,向东遇到路口与 (1,1) 的距离分别是 w 1 , w 2 , ···, w m−1 。道路的每个路口都有一个红绿灯。
时刻 0 的时候,南北向绿灯亮,东西向红灯亮,南北向的绿灯会持续一段
时间(每个路口不同),然后南北向变成红灯,东西向变成绿灯,持续一段时间后,再变成南北向绿灯,东西向红灯。
已知路口 (i, j) 的南北向绿灯每次持续的时间为 g ij ,东西向的绿灯每次持
续的时间为 r ij ,红绿灯的变换时间忽略。
当一辆车走到路口时,如果是绿灯,可以直行、左转或右转。如果是红灯,
可以右转,不能直行或左转。如果到路口的时候刚好由红灯变为绿灯,则视为
看到绿灯,如果刚好由绿灯变为红灯,则视为看到红灯。
每段道路都是双向道路,道路中间有隔离栏杆,在道路中间不能掉头,只
能在红绿灯路口掉头。掉头时不管是红灯还是绿灯都可以直接掉头。掉头的时
间可以忽略。
小蓝时刻 0 从家出发。今天,他接到了 q 个预约的订单,他打算按照订单
的顺序依次完成这些订单,就回家休息。中途小蓝不准备再拉其他乘客。
小蓝的家在两个路口的中点,小蓝喜欢用 x 1 , y 1 , x 2 , y 2 来表示自己家的位
置,即路口 (x 1 ,y 1 ) 到路口 (x 2 ,y 2 ) 之间的道路中点的右侧,保证两个路口相邻(中间没有其他路口)。请注意当两个路口交换位置时,表达的是路的不同两边,路中间有栏杆,因此这两个位置实际要走比较远才能到达。
小蓝的订单也是从某两个路口间的中点出发,到某两个路口间的中点结束。小蓝必须按照给定的顺序处理订单,而且一个时刻只能处理一个订单,不能图省时间而同时接两位乘客,也不能插队完成后面的订单。
小蓝只对 L 市比较熟,因此他只会在给定的 n 条东西向道路和 m 条南北向道路上行驶,而且不会驶出 H 1 , H n , S 1 , S m 这几条道路所确定的矩形区域(可以到边界)。小蓝行车速度一直为 1,乘客上下车的时间忽略不计。请问,小蓝最早什么时候能完成所有订单回到家。
【输入格式】
输入第一行包含两个整数 n, m,表示东西向道路的数量和南北向道路的数量。
第二行包含 n − 1 个整数 h 1 , h 2 , ···, h n−1 。
第三行包含 m − 1 个整数 w 1 , w 2 , ···, w m−1 。
接下来 n 行,每行 m 个整数,描述每个路口南北向绿灯的时间,其中的第i 行第 j 列表示 g ij 。
接下来 n 行,每行 m 个整数,描述每个路口东西向绿灯的时间,其中的第i 行第 j 列表示 r ij 。
接下来一行包含四个整数 x 1 , y 1 , x 2 , y 2 ,表示小蓝家的位置在路口 (x 1 ,y 1 )到路口 (x 2 ,y 2 ) 之间的道路中点的右侧。
接下来一行包含一个整数 q,表示订单数量。
接下来 q 行,每行描述一个订单,其中第 i 行包含八个整数 x i1 , y i1 , x i2 , y i2 ,x i3 , y i3 , x i4 , y i4 ,表示第 i 个订单的起点为路口 (x i1 ,y i1 ) 到路口 (x i2 ,y i2 ) 之间的道路中点的右侧,第 i 个订单的终点为路口 (x i3 ,y i3 ) 到路口 (x i4 ,y i4 ) 之间的道路中点的右侧。
【输出格式】
输出一个实数,表示小蓝完成所有订单最后回到家的最早时刻。四舍五入
保留一位小数。
【样例输入】
2 3
200
100 400
10 20 10
20 40 30
20 20 20
20 20 20
2 1 1 1
1
2 2 1 2 1 2 1 3
【样例输出】
1620.0
【样例说明】
小蓝有一个订单,他的行车路线如下图所示。其中 H 表示他家的位置,S
表示订单的起点,T 表示订单的终点。小明在最后回家时要在直行的红绿灯路
口等绿灯,等待时间为 20。
【评测用例规模与约定】
对于 20% 的评测用例,1 ≤ n, m ≤ 5,1 ≤ q ≤ 10。
对于 50% 的评测用例,1 ≤ n, m ≤ 30,1 ≤ q ≤ 30。
对于所有评测用例,1 ≤ n, m ≤ 100,1 ≤ q ≤ 30,1 ≤ h 1 < h 2 < · · · < h n−1 ≤
100000,1 ≤ w 1 < w 2 < · · · < w m−1 ≤ 100000,1 ≤ g ij ≤ 1000,1 ≤ ri j ≤ 1000,给
定的路口一定合法。
没写。。后补
J: 质数行者
【问题描述】
小蓝在玩一个叫质数行者的游戏。
游戏在一个 n×m×w 的立体方格图上进行,从北到南依次标号为第 1 行到
第 n 行,从西到东依次标号为第 1 列到第 m 列,从下到上依次标号为第 1 层到第 w 层。
小蓝要控制自己的角色从第 1 行第 1 列第 1 层移动到第 n 行第 m 列第 w层。每一步,他可以向东走质数格、向南走质数格或者向上走质数格。每走到一个位置,小蓝的角色要稍作停留。
在游戏中有两个陷阱,分别为第 r 1 行第 c 1 列第 h 1 层和第 r 2 行第 c 2 列第h2 层。这两个陷阱的位置可以跨过,但不能停留。也就是说,小蓝不能控制角色某一步正好走到陷阱上,但是某一步中间跨过了陷阱是允许的。
小蓝最近比较清闲,因此他想用不同的走法来完成这个游戏。所谓两个走法不同,是指小蓝稍作停留的位置集合不同。
请帮小蓝计算一下,他总共有多少种不同的走法。
提示:请注意内存限制,如果你的程序运行时超过内存限制将不得分。
【输入格式】
输入第一行包含两个整数 n, m, w,表示方格图的大小。
第二行包含 6 个整数,r 1 , c 1 , h 1 , r 2 , c 2 , h 2 ,表示陷阱的位置。
【输出格式】
输出一行,包含一个整数,表示走法的数量。答案可能非常大,请输出答
案除以 1000000007 的余数。
【样例输入】
5 6 1
3 4 1 1 2 1
【样例输出】
11
【样例说明】
用 (r,c,h) 表示第 r 行第 c 列第 h 层,可能的走法有以下几种:
1.(1,1,1) − (1,3,1) − (1,6,1) − (3,6,1) − (5,6,1)。
2.(1,1,1) − (1,3,1) − (3,3,1) − (3,6,1) − (5,6,1)。
3.(1,1,1) − (1,3,1) − (3,3,1) − (5,3,1) − (5,6,1)。
4.(1,1,1) − (3,1,1) − (3,3,1) − (3,6,1) − (5,6,1)。
5.(1,1,1) − (3,1,1) − (3,3,1) − (5,3,1) − (5,6,1)。
6.(1,1,1) − (3,1,1) − (5,1,1) − (5,3,1) − (5,6,1)。
7.(1,1,1) − (3,1,1) − (5,1,1) − (5,4,1) − (5,6,1)。
8.(1,1,1) − (1,4,1) − (1,6,1) − (3,6,1) − (5,6,1)。
9。(1,1,1) − (1,6,1) − (3,6,1) − (5,6,1)。
10.(1,1,1) − (3,1,1) − (3,6,1) − (5,6,1)。
11.(1,1,1) − (3,1,1) − (5,1,1) − (5,6,1)。
【评测用例规模与约定】
对于 30% 的评测用例 1 ≤ n,m,w ≤ 50。
对于 60% 的评测用例 1 ≤ n,m,w ≤ 300。
对于所有评测用例,1 ≤ n,m,w ≤ 1000,1 ≤ r 1 ,r 2 ≤ n, 1 ≤ c 1 ,c 2 ≤ m,
1 ≤ h 1 ,h 2 ≤ w,陷阱不在起点或终点,两个陷阱不同。
后补。。