AtCoder Beginner Contest 042 题解
🌸欢迎来到我的算法小屋🌸
前言
写大体感觉,总结,文章写完之后补充。
| Task Name | |
| A | Iroha and Haiku (ABC Edition) |
| B | Iroha Loves Strings (ABC Edition) |
| C | Iroha's Obsession |
| D | Iroha and a Grid |
A
题目描述

题目大意如下:
输入三个数,假如输入的三个数中有两个5,一个7,那么就符合要求,其他的都不行
解题报告
A是签到水题,可以数组模拟哈希表,也可以循环去统计5和7的个数
参考代码(C++)
/* 伊吕波喜欢俳句。俳句是日本诗歌的一种缩写形式。 俳句由 5、7 和 5 个音节的三个短语组成,按此顺序排列。 为了创造俳句,Iroha 提出了三个不同的短语。这些短语分别有 A、B 和 C 音节。 确定她是否可以按某种顺序使用每个短语一次来构建俳句。 */ #include<bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define N 520 #define mem(a,b) memset(a,b,sizeof(a)) typedef long long LL; int n; int a[3],h[10]; void run(){ ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); } inline int read(){ int x=0,f=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')f=-1; c=getchar(); } while(c>='0'&&c<='9'){ x=(x<<1)+(x<<3)+(c^48); c=getchar(); } return x*f; } int main(){ run(); for(int i = 0;i < 3;i++){ cin >> a[i]; h[a[i]] ++; } if(h[5] == 2 && h[7] == 1) puts("YES"); else puts("NO"); return 0; }
要点总结
练打字速度的了....
B
题目描述

题目大意如下:
给咱们N个字符串,让我们输出这N个字符串按照字典序产生的最终序列。
解题报告
先普及一下字典序的知识吧。

其实也不用想得特别晦涩难懂,因为abcd..xyz的升序,在ASCII码上也是从小到大的升序,那么string + sort函数的方式就挺简约了。
参考代码(C++)
/* 连接给定的字符串,产生长的字符串 */ #include<bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define N 520 #define mem(a,b) memset(a,b,sizeof(a)) typedef long long LL; int T; std::vector<string> v; void run(){ ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); } inline int read(){ int x=0,f=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')f=-1; c=getchar(); } while(c>='0'&&c<='9'){ x=(x<<1)+(x<<3)+(c^48); c=getchar(); } return x*f; } int main(){ run(); int n,k; cin >> n >> k; while(n--){ string str; cin >> str; v.push_back(str); } sort(v.begin(),v.end()); for(auto it: v){ cout <<it; } return 0; }
要点总结
stl还是蛮香的..
C
题目描述
、
题目大意是让咱们找到一个数字,这个数字里面不包含这个人罗列出来的,它讨厌的这些数字。
解题报告
可以直接枚举,然后通过while + 取模运算符 + 整数除法来逐一判断每一位是否包含这人讨厌的数字,枚举到第一个完全由ta不讨厌的数字组成的整数的时候,就可以跳出枚举,输出结果了。
参考代码(C++)
#include<bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define D 15 #define mem(a,b) memset(a,b,sizeof(a)) typedef long long LL; int n,k; int h[D]; void run(){ ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); } inline int read(){ int x=0,f=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')f=-1; c=getchar(); } while(c>='0'&&c<='9'){ x=(x<<1)+(x<<3)+(c^48); c=getchar(); } return x*f; } int main(){ run(); cin >> n >> k; mem(h,0); for(int i = 1;i <= k;i++){ int x; cin >>x; h[x] ++; } //题目中的N是限制,不是金额的限制 for(int i = n; ;i++){ int x = i; bool dislike = false; while(x){ if(h[x%10] == 0){ x/=10; }else{ dislike = true; break; } } if(!dislike) { cout <<i<<'\n'; break; }else continue; } return 0; }
要点总结
暂无
D
题目描述

题目大意:
给了咱们一个高H宽W的方格,现在咱们的位置在左上角( Iroha is now standing in the top-left cell.),
咱们只能向下或者向右走,需要咱们走到右下角(she reaches the bottom-right cell.)。
但是在左下角的那片区域是不能通过的( bottom AA rows and the leftmost BB columns)
现在问,咱们走到右下角的终点的方案一共有多少种(Find the number of ways she can travel to the bottom-right cell.)
解决报告
问咱们一共有多少种方案,以及提示说最后的结果很大,特别是看到十万的数据范围,然后需要取模的时候,其实就可以向着组合数学的方向思考了。因为当前每走的一个格子,都是一种选择方案。
本题主要的思路是参考这位大佬的:
(AtCoder - 1974)いろはちゃんとマス目 / Iroha and a Grid(乘法逆元+组合计数)
我的代码可能思路更加清晰一点,仅供参考
参考代码(C++)
#include <bits/stdc++.h> using namespace std; /*宏定义*/ #define MOD 1000000007 #define INF 0x3f3f3f3f #define PI 3.141592653589793238462 #define N 100010 #define mem(a,b) memset(a,b,sizeof(a)) #define x first #define y second typedef long long ll; const double eps = 1e-8; int t,n; /* * 常用函数 */ //最大公约数 ll gcd(ll a,ll b) {return b==0 ? a : gcd(b,a%b);} //最小公倍数 ll lcm(ll a,ll b) {return a*b / gcd(a,b);} //lowbit运算 int lowbit(int x) {return x & (-x);} //快速幂 a的b次,取mod ll qmi(ll a,ll b,ll mod) { ll ans = 1; while(b) { if(b & 1) ans = ans * a % mod; a = a * a % mod; b >>= 1; } return ans; } //组合数学的初始化阶乘数组 ll fact[N]; void init_fact(){ fact[0] = 1; for(int i = 1; i < N;i++){ fact[i] = 1ll*fact[i-1]*i % MOD; } } //计算乘法逆元 —— 公式 ll inverse(ll a){ return qmi(a,MOD-2,MOD); } //计算组合数 —— 组合数的公式,分式部分用乘法逆元表示 ll C(ll n,ll m){ return(1ll * fact[n] * inverse(fact[m]) % MOD)* inverse(fact[n-m])%MOD; } //cin 、 cout 优化 void run(){ ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); } //快读 inline int read(){ int x=0,f=1; char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')f=-1; c=getchar(); } while(c>='0'&&c<='9'){ x=(x<<1)+(x<<3)+(c^48); c=getchar(); } return x*f; } int main(){ run(); int h,w,a,b; cin >> h >> w >> a >> b; ll ans = 0; init_fact(); //b是左下角不能走的区域的边长,w是整体的下边长 for(int i = b+1;i <=w;i++){ ans = (ans+C(h-a+i-2,h-a-1)*C(w+a-i-1,a-1)%MOD)%MOD; } cout << ans; return 0; }
要点总结
在组合数中,首先要清楚组合数的公式是这种的,
,因为整数除法会出现精确缺失的清楚,因此要结合费马小定理来求乘法逆元,最后就可以化除法为乘法。

ABC第42场,第四题的组合数是主要想记录的
浙公网安备 33010602011771号