试题 A: 空间
5分 67108864
void run()
{
ll ans = 256*1024*1024/4;
cout << ans << endl;
}
试题 B: 卡片
5分 3181
void run()
{
int i, j;
for (i = 0; i <= 9; i ++ ) st[i] = 2021;
for (i = 0; ; i ++ ) {
if(0 <= i && i < 10) {
st[i] -= 1;
if(st[i] == 0) {
cout << i;
break;
}
}
else if(10 <= i &&i < 100) {
int a = i%10, b = i/10%10;
st[a] -= 1, st[b] -= 1;
if(st[a] == 0 || st[b] == 0) {
cout << i;
break;
}
}
else if(100 <= i && i < 1000) {
int a= i%10, b= i/10%10, c = i/100%10;
st[a] -= 1, st[b] -= 1, st[c] -= 1;
if(st[a] == 0 ||st[b] == 0 || st[c] == 0) {
cout << i;
break;
}
}
else if(1000<= i && i < 10000){
int a= i%10, b= i/10%10, c = i/100%10, d = i/1000%10;
st[a] -= 1, st[b] -= 1, st[c] -= 1, st[d] -= 1;
if(st[a] == 0 ||st[b] == 0 || st[c] == 0 || st[d] == 0) {
cout << i;
break;
}
}
else {
for (j = 0; j <= 9; j ++ ) cout << st[i] << ' ';
break;
}
}
}
这样写会简单一些
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
int s[10];
bool check(int x) {
while (x) {
int t = x % 10;
x = x / 10;
if (--s[t] < 0) return false;
}
return true;
}
int main() {
for (int i = 0; i < 10; i++) s[i] = 2021;
for (int i = 1;; i++) {
if (!check(i)) {
//检查该数是否已经用完,不够用即最后一个数为所求的数
cout << i - 1 << endl;
return 0;
}
}
}
试题 C: 直线
0分
typedef pair<double, double> PII;
set<PII> st;
void run() // 47753 始终多一些,之前是因为整除的原因
{
double i,j, x, y;
int n = 20, m = 21;
for (i = 0; i < n; i ++ ) {
for (j = 0; j < m; j ++ ) {
for (x = 0; x < n; x ++ ) {
for (y = 0; y < m; y ++ ) {
if(i == x && j == y) continue;
double k, b;
if(x-i == 0) continue;
else if(y-j == 0) continue;
else k = (y-j)*1.0/(x-i),b = y - k*x; // 除0
// deb2(k, b);
st.insert({k, b});
}
}
}
}
cout << st.size() + n+m;
}
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = a; i <= b; i ++ )
#define deb2(x, y) cout << #x << '=' << x << ',' << #y << '=' << y <<endl
#define deb3(x, y, z) cout << #x <<'=' << x << ',' << #y << '=' << y << ',' << #z << '=' << z << endl
using namespace std;
const int N = 2e5 + 10, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<pii, int> PII;
set<PII> st;
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a%b);
}
void run() // 40257
{
int x1, y1, x2, y2;
int n = 20, m = 21;
for (x1 = 0; x1 < n; x1 ++) {
for (y1 = 0; y1 < m; y1 ++) {
for (x2 = 0; x2 < n; x2 ++ ) {
for (y2 = 0; y2 < m; y2 ++ ) {
if(x1 == x2 && y1 == y2) continue;
int a = y2-y1;
int b = x1-x2;
int c = y1*x2-y2*x1;
int m = gcd(gcd(a, b), c);
a /= m, b /= m, c /= m;
st.insert({{a, b}, c});
}
}
}
}
cout << st.size() << endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0);
cout << fixed; cout.precision(18);
int T = 1;
//cin >> T;
while(T -- ) run();
}
试题 D: 货物摆放
10分
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = a; i <= b; i ++ )
#define deb2(x, y) cout << #x << '=' << x << ',' << #y << '=' << y <<endl
using namespace std;
const int N = 2e5 + 10, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int, int> PII;
int a[N];
void run()
{
ll n = 2021041820210418;
vector<ll> q;
ll i; //怎么我悟不出: n一定是由n的因子组成的
for (i = 1; i *i <= n; i ++ ) {
if(n % i == 0) {
q.push_back(i);
if(i*i != n) q.push_back(n/i);
}
}
ll res = 0;
for (auto a : q) {
for (auto b : q) {
for (auto c : q) {
if(a*b*c == n) res += 1;
}
}
}
cout << res << endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0);
cout << fixed; cout.precision(18);
int T = 1;
//cin >> T;
while(T -- ) run();
}
试题 E: 路径
10266837 flody可以跑耶耶耶耶耶耶15分到手
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = a; i <= b; i ++ )
#define deb2(x, y) cout << #x << '=' << x << ',' << #y << '=' << y <<endl
using namespace std;
const int N = 2e5 + 10, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int, int> PII;
int g[3000][3000];
int n = 2021;
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a%b);
}
void run()
{
memset(g, 0x3f, sizeof g);
int i, j;
for (i = 1; i <= n; i ++ ) {
for (j = max(1,i-21); j <= min(n, i+21); j ++ ) { // j
int t = gcd(i, j);
g[i][j] = g[j][i] = i*j/t;
}
}
int k;
for (k = 1; k <= n; k ++ )
for (i = 1; i <= n; i ++ )
for (j = 1; j <= n; j ++ ) {
if(g[i][j] > g[i][k] + g[k][j])
g[i][j] = g[i][k] + g[k][j];
}
cout << g[1][n] << endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0);
cout << fixed; cout.precision(18);
int T = 1;
//cin >> T;
while(T -- ) run();
}
用dij写速度也不快
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = a; i <= b; i ++ )
#define deb2(x, y) cout << #x << '=' << x << ',' << #y << '=' << y <<endl
using namespace std;
const int N = 2e5 + 10, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int, int> PII;
int g[3000][3000];
bool st[2030];
int d[2030];
int n = 2021;
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a%b);
}
void dij() {
d[1] = 0; // 初始化错误
priority_queue<PII> q;
q.push({0, 1});
while(!q.empty()) {
PII t = q.top(); q.pop();
int u = t.second;
if(st[u] == 1) continue;
st[u] == 1;
for (int i = 1; i <= n; i ++ ) {
if(i == u) continue;
if(d[i] > d[u] + g[u][i]) {
d[i] = d[u] + g[u][i];
q.push({d[i], i});
}
}
}
}
void run()
{
memset(g, 0x3f, sizeof g);
memset(d, 0x3f, sizeof d);
int i, j;
for (i = 1; i <= n; i ++ ) {
for (j = max(1,i-21); j <= min(n, i+21); j ++ ) { // j
int t = gcd(i, j);
g[i][j] = g[j][i] = i*j/t;
}
}
dij();
cout << d[n] << endl;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0);
cout << fixed; cout.precision(18);
int T = 1;
//cin >> T;
while(T -- ) run();
}
试题 F: 时间显示
怎么办,这道题显得我很弱智,我没了,我是题目理解怪物吧
#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = a; i <= b; i ++ )
#define deb2(x, y) cout << #x << '=' << x << ',' << #y << '=' << y <<endl
using namespace std;
const int N = 2e5 + 10, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int, int> PII;
int m[] = {0, 31, 28, 31, 20, 31, 30, 31, 31, 30, 31, 30, 31};
void run()
{
ll x; cin >> x;
int k = 24*3600;
int i, j, d;
x/= 1000; // 我服了,题目给的毫秒
for (i = 1970; i <= 2020; i ++) { // 我天,我是题目理解怪物吗?
m[2] = 28;
if(i % 4 == 0 && i % 100 || i % 400 == 0) m[2] = 29;
for (j = 1; j <= 12; j ++ ) {
for (d = 1; d <= m[j]; d ++ ) {
deb2(x, k);
if(x >= k) x -= k;
else {
int h = x / 3600;
int m = x / 60 % 60;
int s = x % 60;
printf("%02d:%02d:%02d", h, m, s);
return ;
}
}
}
}
}
signed main()
{
// ios::sync_with_stdio(false), cin.tie(0);
// cout << fixed; cout.precision(18);
int T = 1;
//cin >> T;
while(T -- ) run();
}
void run()
{
ll x; cin >> x; x /= 1000;
int k = 24*3600;
x %= k;
int h = x /3600;
int m = x / 60 % 60;
int s = x % 60;
printf("%02d:%02d:%02d", h, m, s);
}
set遍历的方法
#include<bits/stdc++.h>
using namespace std;
set<int> s;
int a[100];
int main()
{
s.clear();
int k = 9;
int cnt = 0;
for(int i = 1;i <= 10;++i) s.insert(i*k%7);
// for(auto it = s.begin();it != s.end();it++) {
// a[cnt++] = *it;
// }
for(set<int>::iterator it = s.begin();it != s.end();it++) {
a[cnt++] = *it;
}
for(int i = 0;i < cnt;++i) {
cout << a[i] << ' ';
}
cout << endl;
}
试题 G: 砝码称重
正解,注意数组要开大一点,不然取min
#include <iostream>
using namespace std;
const int N = 110, M = 2e5 + 10;
bool f[N][M];
int w[N];
int main()
{
// 请在此输入您的代码
int n; cin >> n;
int i, j, sum = 0;
for (i = 1; i <= n; i ++ ) cin >> w[i], sum += w[i];
f[0][0] = 1;
for (i = 1; i <= n; i ++ ) {
for (j = 0; j <= sum; j ++ ) {
f[i][j] = f[i-1][j] + f[i-1][abs(j-w[i])]
+ f[i-1][j+w[i]];
// cout << f[i][j] << ' ';
}
// cout << endl;
}
int ans = 0;
for (i = 1; i <= sum; i ++ ) if(f[n][i]) ans += 1;
cout << ans << endl;
return 0;
}
试题 H: 杨辉三角形
😊😍y总这个方法好用,这是估算的方法
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int n;
/*
组合数和杨辉三角:第i行第j列的数都是组合数C(i, j) (i,j从0开始)
C(n, 1) = n --> 对应从左向右看斜着的第二列! ---> 一定有解
由于杨辉三角左右对称(C(a, b) == C(a, a-b)),又由于找第一次出现,因此一定在左边,右边可以直接删掉!
1 ---> C(0, 0)
1
1 2 ---> C(2, 1)
1 3 ---> C(2n, n)
1 4 6 ---> C(4, 2)
1 5 10
1 6 15 20 ---> C(6, 3)
n最大1e9,C(34, 17) > 1e9, C(32, 16) < 1e9,因此只要枚举前16个斜行即可!
性质:
1. 每一斜行从上到下递增
2. 每一横行从中间到两边依次递减
因此我们直接从中间对称轴倒序二分找起即可!
C(r, k)对应的顺序值为:(r + 1) * r / 2 + k + 1
二分的左右端点:l:2k,r:max(n, l)
右端点一定不能比左端点小!
特例:否则当n=1时,会出问题!
*/
// C(a, b) = a!/b!(a-b)! = a * (a-1) .. b个 / b!
LL C(int a, int b){
LL res = 1;
for(int i = a, j = 1; j <= b; i --, j ++){
res = res * i / j;
// 大于n已无意义,且防止爆LL
if(res > n) return res;
}
return res;
}
bool check(int k){
// 二分该斜行,找到大于等于该值的第一个数
// 左边界2k,右边界为max(l, n)取二者最大即可!
int l = 2 * k, r = max(n, l);
while(l < r){
int mid = l + r >> 1;
if(C(mid, k) >= n) r = mid;
else l = mid + 1;
}
if(C(r, k) != n) return false;
// C(r, k)的从0开始的顺序!
cout << 1ll * (r + 1) * r / 2 + k + 1 << endl;
return true;
}
int main(){
cin >> n;
// 从第16斜行枚举即可!
for(int k = 16; ; k --)
if(check(k)) break;
return 0;
}