AtCoder Beginner Contest 178 A - E 解题报告
题目链接
A - Not
思路:
无
代码:
/*
* @Author : nonameless
* @Date : 2020-09-13 19:55:56
* @LastEditors : nonameless
* @LastEditTime : 2020-09-13 20:00:55
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define toStr(name) (#name)
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b,a % b):a;}
inline ll gcd(ll a, ll b) { return b ? gcd(b,a % b):a;}
inline int lcm(int a, int b) { return a * b / gcd(a, b); }
template<class T>
inline void read(T &x){
x = 0;
int f = 1;
char c = getchar();
while(c < '0' || c > '9') if(c == '-') { f = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
x = x * f;
}
template<class T>
inline void out(string a, T x){ cout << a << " = " << x << endl; }
int main(){
int x; read(x);
if(x == 0) puts("1");
if(x == 1) puts("0");
return 0;
}
B - Product Max
思路:
显然答案只会出现在端点的相乘上,所以暴力枚举出四种情况取 \(max\) 即可。
代码:
/*
* @Author : nonameless
* @Date : 2020-09-13 20:02:06
* @LastEditors : nonameless
* @LastEditTime : 2020-09-14 00:51:31
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define toStr(name) (#name)
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b,a % b):a;}
inline ll gcd(ll a, ll b) { return b ? gcd(b,a % b):a;}
inline int lcm(int a, int b) { return a * b / gcd(a, b); }
template<class T>
inline void read(T &x){
x = 0;
int f = 1;
char c = getchar();
while(c < '0' || c > '9') if(c == '-') { f = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
x = x * f;
}
template<class T>
inline void out(string a, T x){ cout << a << " = " << x << endl; }
int main(){
ll a, b, c, d; cin >> a >> b >> c >> d;
ll ans = -LNF;
ans = max(ans, a * c);
ans = max(ans, a * d);
ans = max(ans, b * c);
ans = max(ans, b * d);
cout << ans << endl;
return 0;
}
C - Ubiquity
思路:
直接考虑不方便,所以我们考虑不合法的方案数。
先用快速幂算出 \(10^n\) 即总方案数。
然后枚举不合法的情况:
- 只有 \(0\) 的情况:\(\sum_{i=1}^nC_n^i\times 8^{n-i}\)。(\(i\) 是 \(0\) 出现的个数)
- 只有 \(9\) 的情况:与 \(0\) 的一样
- 没有 \(0, 9\) 的情况:\(8^n\)。
然后减去上述情况即可。
代码:
/*
* @Author : nonameless
* @Date : 2020-09-13 20:14:14
* @LastEditors : nonameless
* @LastEditTime : 2020-09-13 20:38:55
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define toStr(name) (#name)
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b,a % b):a;}
inline ll gcd(ll a, ll b) { return b ? gcd(b,a % b):a;}
inline int lcm(int a, int b) { return a * b / gcd(a, b); }
template<class T>
inline void read(T &x){
x = 0;
int f = 1;
char c = getchar();
while(c < '0' || c > '9') if(c == '-') { f = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
x = x * f;
}
template<class T>
inline void out(string a, T x){ cout << a << " = " << x << endl; }
const int mod = 1e9 + 7;
const int N = 1e6 + 10;
ll f[N];
ll qpow(ll a, ll b){
ll res = 1;
while(b){
if(b & 1) res = res * a % mod;
b >>= 1;
a = a * a % mod;
}
return res;
}
ll C(ll a, ll b){
return f[a] * (qpow(f[b] * f[a - b] % mod, mod - 2)) % mod;
}
int main(){
f[0] = 1;
for(int i = 1; i < N; i ++) f[i] = f[i - 1] * i % mod;
ll n; read(n);
if(n == 1) puts("0");
else{
ll ans = qpow(10, n);
ll t1 = 0;
for(int i = 1; i <= n; i ++){
t1 = (t1 + C(n, i) * qpow(8, n - i) * 2 % mod) % mod;
}
t1 = (t1 + qpow(8, n)) % mod;
ans = (ans - t1 + mod) % mod;
cout << ans << endl;
}
return 0;
}
D - Redistribution
思路:
设 \(f[i][j]\) :长度为 \(i\) 且和为 \(j\) 的序列的个数。
那么转移方程有:\(f[i][j] = f[i][j] + f[i-1][j-k](3\leq k\leq j)\)
但是这样枚举是有三重循环,显然超时,所以考虑优化掉一重循环。
观察方程可以发现 \(f[i-1][j-k]\) 是可以用前缀和求出来的,因为他就是上一层计算出来的,所以我们可以在处理完 \(i\) 的时候,求出当前长度的前缀和供下一层使用。
注意边界的初始化。对长度为 \(0\) 的也要求一次前缀和。
代码:
/*
* @Author : nonameless
* @Date : 2020-09-13 20:40:53
* @LastEditors : nonameless
* @LastEditTime : 2020-09-14 00:59:44
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define toStr(name) (#name)
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b,a % b):a;}
inline ll gcd(ll a, ll b) { return b ? gcd(b,a % b):a;}
inline int lcm(int a, int b) { return a * b / gcd(a, b); }
template<class T>
inline void read(T &x){
x = 0;
int f = 1;
char c = getchar();
while(c < '0' || c > '9') if(c == '-') { f = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
x = x * f;
}
template<class T>
inline void out(string a, T x){ cout << a << " = " << x << endl; }
const int N = 2e3 + 10;
const int mod = 1e9 + 7;
int f[N / 3][N];
int main(){
int s; read(s);
ll ans = 0;
f[0][0] = 1;
for(int i = 1; i <= s; i ++) f[0][i] = 1;
for(int i = 1; i <= s / 3; i ++){
for(int j = 3; j <= s; j ++){
f[i][j] = (f[i][j] + f[i - 1][j - 3]) % mod;
ans = (ans + f[i][s]) % mod;
}
for(int j = 1; j <= s; j ++) f[i][j] = (f[i][j] + f[i][j - 1]) % mod;
}
cout << ans << endl;
return 0;
}
E - Dist Max
思路:
这其实就是一个最远曼哈顿距离的模板题(奈何我不知道)。
由:\(|a - b| = max(a - b, b - a)\);
那么可以将 \(|x_i-x_j|+|y_i-y_j|\) 变为在下面四种情况中取 \(max\) :
- \((x_i-x_j) + (y_i-y_j)\)
- \((x_i-x_j)+(y_j-y_i)\)
- \((x_j-x_i)+(y_i-y_j)\)
- \((x_j-x_i)+(y_j-y_i)\)
我们利用交换律将一个点的坐标放在一起:
- \((x_i+y_i)+(-x_j-y_j)\)
- \((x_i-y_i)+(-y_i+y_j)\)
- \((-x_i+y_i)+(x_j-y_j)\)
- \((-x_i-y_i)+(x_j+y_j)\)
我们可以发现其实就只有两种情况了(\(1,4\) 是一种情况,\(2, 3\) 是一种情况)即:
- \((x_i+y_i)+(-x_j-y_j)\)
- \((x_i-y_i)+(-y_i+y_j)\)
代码:
/*
* @Author : nonameless
* @Date : 2020-09-14 00:38:45
* @LastEditors : nonameless
* @LastEditTime : 2020-09-14 00:45:05
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define toStr(name) (#name)
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const double eps = 1e-6;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b,a % b):a;}
inline ll gcd(ll a, ll b) { return b ? gcd(b,a % b):a;}
inline int lcm(int a, int b) { return a * b / gcd(a, b); }
template<class T>
inline void read(T &x){
x = 0;
int f = 1;
char c = getchar();
while(c < '0' || c > '9') if(c == '-') { f = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
x = x * f;
}
template<class T>
inline void out(string a, T x){ cout << a << " = " << x << endl; }
vector<int> v1, v2, v3, v4;
bool cmp(int a, int b) { return a > b; }
int main(){
int n; read(n);
for(int i = 1; i <= n; i ++){
int x, y;
read(x); read(y);
v1.pb(x + y);
v2.pb(-x - y);
v3.pb(-x + y);
v4.pb(x - y);
}
sort(all(v1), cmp); sort(all(v2), cmp); sort(all(v3), cmp); sort(all(v4), cmp);
int ans = max(v1[0] + v2[0], v3[0] + v4[0]);
cout << ans << endl;
return 0;
}