这个div4还是比较基础的,比赛的时候写了4题就睡觉去了,早上起来花了几十分钟把剩余的题补了,总的来说还是比较适合初学者的。
题目就不粘贴了。
就是把一个数 n n n表示成round
数,如 9876 9876 9876,输出 9000 , 800 , 70 , 6 9000,800,70,6 9000,800,70,6, 5009 5009 5009,输出 5000 , 9 5000,9 5000,9,例子一看就知道怎么搞了。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a > b ? b : a; }
const double eps = 1e-7;
#define endl '\n'
#define pb(a) push_back(a)
#define ALL(x) x.begin(), x.end()
int mypow(int x, int n) {
for (int i = 1; i <= n; ++i) x *= 10;
return x;
}
int main() {
// ios::sync_with_stdio(false);
int t;
scanf("%d", &t);
while (t--) {
string s;
cin >> s;
int n = s.size() - 1;
vector<int> ans;
for (int i = 0; i < s.size(); ++i) {
if (s[i] != '0') {
ans.pb(mypow(s[i] - '0', n));
}
n--;
}
printf("%d\n", ans.size());
for (auto it : ans) printf("%d ", it);
printf("\n");
}
return 0;
}
B题有点恶心,写了很多的判断语句,首先需要知道
然后看题目你最终要表示成什么数的和,如果是奇数,那么就是 n = ∑ 1 k − 1 1 + ( n − k + 1 ) n = \sum_{1}^{k-1} 1+(n-k+1) n=∑1k−11+(n−k+1),如果表示成偶数,那么就是 n = ∑ 1 k − 1 2 + n − 2 × ( k − 1 ) n=\sum_{1}^{k-1}2+n-2 \times (k-1) n=∑1k−12+n−2×(k−1),如果表示不出来就是NO
。
还有一些特殊判断的,如果n=k
,那么直接输出 k k k个 1 1 1,如果k是偶数并且n是奇数,那直接NO
。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a > b ? b : a; }
const double eps = 1e-7;
#define endl '\n'
#define pb(a) push_back(a)
#define ALL(x) x.begin(), x.end()
int main() {
// ios::sync_with_stdio(false);
int t;
scanf("%d", &t);
while (t--) {
ll n;
int k;
scanf("%lld%d", &n, &k);
if (k & 1 == 0 && n % 2 == 1) {
puts("NO");
continue;
}
if (n == k) {
puts("YES");
for (int i = 1; i <= k; ++i) printf("1 ");
puts("");
continue;
}
if (k & 1) {
if (n & 1 && n - k + 1 >= 1) {
printf("YES\n");
for (int i = 1; i <= k - 1; ++i) printf("1 ");
printf("%lld\n", n - k + 1);
} else if (n % 2 == 0 && n - 2 * (k - 1) >= 2) {
printf("YES\n");
for (int i = 1; i <= k - 1; ++i) printf("2 ");
printf("%lld\n", n - 2 * (k - 1));
} else {
printf("NO\n");
}
} else {
if (n % 2 == 0 && n - k + 1 >= 2) {
printf("YES\n");
for (int i = 1; i <= k - 1; ++i) printf("1 ");
printf("%lld\n", n - k + 1);
} else if (n % 2 == 0 && n - 2 * (k - 1) >= 2) {
printf("YES\n");
for (int i = 1; i <= k - 1; ++i) printf("2 ");
printf("%lld\n", n - 2 * (k - 1));
} else {
printf("NO\n");
}
}
}
return 0;
}
C题找规律题,写两个例子就知道了。
n=3
数: 1 2 4 5 7 8 10 11 13
下标: 1 2 3 4 5 6 7 8 9
将数与下标相减:
0 0 1 1 2 2 3 3 4...
n=4
1 2 3 5 6 7 9 10 11 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12
0 0 0 1 1 1 2 2 2 3 3 3...
可以发现是有规律的,应该看得出来,我们设数与下标相减为 p p p,那么第 k k k个数就是 p + k p+k p+k,所以只要算出 p p p即可。
易发现 n = 3 n=3 n=3时是以 2 2 2为周期的, n = 4 n=4 n=4时是以 3 3 3为周期的,所以每一组都是以 n − 1 n-1 n−1为周期的,那么 p = ⌈ k n − 1 ⌉ − 1 p=\left \lceil \frac{k}{n-1} \right \rceil -1 p=⌈n−1k⌉−1,ok!
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a > b ? b : a; }
const double eps = 1e-7;
#define endl '\n'
#define pb(a) push_back(a)
#define ALL(x) x.begin(), x.end()
int main() {
// ios::sync_with_stdio(false);
int t;
scanf("%d", &t);
while (t--) {
ll n, k;
scanf("%lld%lld", &n, &k);
ll p;
if (k % (n - 1) == 0)
p = k / (n - 1);
else
p = k / (n - 1) + 1;
printf("%lld\n", p - 1 + k);
}
return 0;
}
模拟题,题目看懂即可。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a > b ? b : a; }
const double eps = 1e-7;
#define endl '\n'
#define pb(a) push_back(a)
#define ALL(x) x.begin(), x.end()
int a[1010];
int main() {
// ios::sync_with_stdio(false);
int t;
scanf("%d", &t);
while (t--) {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
int sa = 0, sb = 0;
int pa = 1, pb = n;
int cnt = 0;
int pre = 0;
while (pa <= pb) {
int tmp = 0;
while (tmp <= pre && pa <= pb) {
tmp += a[pa++];
}
pre = tmp;
sa += tmp;
cnt++;
if (pa > pb) break;
int tmp2 = 0;
while (tmp2 <= pre && pb >= pa) {
tmp2 += a[pb--];
}
pre = tmp2;
sb += tmp2;
cnt++;
}
printf("%d %d %d\n", cnt, sa, sb);
}
return 0;
}
E题用set会mle,用map也mle,看来stl是用空间换时间的,这题用数组标记就行了。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N = 1e7;
const int INF = 0x3f3f3f3f;
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a > b ? b : a; }
const double eps = 1e-7;
#define endl '\n'
#define pb(a) push_back(a)
#define ALL(x) x.begin(), x.end()
int n, a[8002];
int f[8002];
int main() {
// ios::sync_with_stdio(false);
int t;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", a + i);
f[a[i]]++;
}
int cnt = 0;
for (int i = 1; i <= n - 1; ++i) {
int sum = a[i];
for (int j = i + 1; j <= n; ++j) {
sum += a[j];
if (sum > n) break;
if (f[sum]) {
cnt += f[sum];
f[sum] = 0;
}
}
}
for (int i = 1; i <= n; ++i) {
f[i] = 0;
}
printf("%d\n", cnt);
}
return 0;
}
构造题,细节有点多。
下面是我的构造方法:
不考虑具体细节,首先先把 n 0 n_0 n0消掉, 000 ⋯ 0 ⏟ n 0 + 1 \begin{matrix} \underbrace{ 000\cdots0 } \\ n_0+1 \end{matrix} 000⋯0n0+1,然后在两侧加入 1 1 1,这时 n 1 = n 1 − 2 n_1=n_1-2 n1=n1−2,然后再在一侧加 n 2 n_2 n2个 1 1 1即可。
但是有很多细节。
因为要频繁头插尾插,可以用deque
完成。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a > b ? b : a; }
const double eps = 1e-7;
#define endl '\n'
#define pb(a) push_back(a)
#define ALL(x) x.begin(), x.end()
int n0, n1, n2;
void solve() {
deque<char> d;
for (int i = 1; i <= n0; ++i) d.push_back('0');
if (n0) d.push_back('0'); //细节1
if (!n0 && n1) d.push_back('0'); //细节2
int f = 0;
if (n1 >= 1) d.push_front('1'), n1--, f = 1;
if (n1 >= 1) d.push_back('1'), n1--;
if (!f && n2) d.push_front('1'); //细节3
for (int i = 1; i <= n2; ++i) d.push_front('1');
n2 = 0;
if (n1) {
while (n1 >= 2) {
d.push_front('0');
d.push_front('1');
n1 -= 2;
}
if (n1 == 1) {
d.push_back('0');
}
n1 = 0;
}
for (auto it : d) {
printf("%c", it);
}
printf("\n");
}
int main() {
// ios::sync_with_stdio(false);
int t;
scanf("%d", &t);
while (t--) {
scanf("%d%d%d", &n0, &n1, &n2);
solve();
}
return 0;
}
一道可以算是经典dfs
题,生成这种有条件的序列。还是蛮水的。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a > b ? b : a; }
const double eps = 1e-7;
#define endl '\n'
#define pb(a) push_back(a)
#define ALL(x) x.begin(), x.end()
int n;
int ans[1010];
bool vis[1010];
bool f;
void dfs(int pre, int k) {
if (k == n + 1) {
f = true;
return;
}
for (int i = 1; i <= n; ++i) {
if (k == 1 && !vis[i]) {
vis[i] = 1;
ans[k] = i;
dfs(i, k + 1);
if (f) return;
vis[i] = 0;
} else {
if (!vis[i] && abs(i - pre) >= 2 && abs(pre - i) <= 4) {
vis[i] = 1;
ans[k] = i;
dfs(i, k + 1);
if (f) return;
vis[i] = 0;
}
}
}
}
int main() {
// ios::sync_with_stdio(false);
int t;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
memset(vis, 0, sizeof(vis));
memset(ans, 0, sizeof(ans));
f = 0;
dfs(0, 1);
int cnt = 0;
for (int i = 1; i <= n; ++i) {
if (ans[i]) cnt++;
}
if (cnt == n) {
for (int i = 1; i <= n; ++i) {
printf("%d ", ans[i]);
}
printf("\n");
} else {
printf("-1\n");
}
}
return 0;
}