2022广西师范大学暑期训练赛
思路:
我是把第一个位置放1,最后一个位置放1,中间放0的,其实也可以是第一个位置放2,其他位置放0。
代码:
int main() {
int T = read();
while(T--) {
int n = read();
if(n == 1) {
cout << 2 << endl;
}else {
cout << 1;
for(int i = 2; i < n; i++) cout << 0;
cout << 1 << endl;
}
}
return 0;
}
思路:
比1大的自然数都可以分解质因数。
非质数可以分解成质数相乘的形式;而质数至少可以写成1乘以质数本身的形式,所以比1大的自然数都可以分解质因数。
代码:
signed main() {
int T = read();
while(T--) {
int s = read();
if(s < 2) cout << "NO" << endl;
else cout << "YES" << endl;
}
return 0;
}
思路:
把每个连续的一段的长度存起来,从大到小排序,取前m个就行。
代码:
int main() {
int T = read();
while(T--) {
int n = read(), m = read();
string s; cin >> s;
memset(w, 0, sizeof w);
int k = 0;
char last = 'x';
for(int i = 0; i < n; i++) {
if(s[i] == last) w[k]++;
else {
last = s[i];
k++;
w[k]++;
}
}
sort(w + 1, w + 1 + k, cmp);
int ans = 0;
//for(int i = 1; i <= k; i++) cout << w[i] << endl;
for(int i = 1; i <= min(m, k); i++) ans += w[i];
cout << ans << endl;
}
return 0;
}
思路:
让1排在一队,0排在一队,2就跟着1那队排,所以2可以看成1.故统计1和2的总个数即为答案。
代码:
int main() {
int T = read();
while(T--) {
int n = read();
int ans = 0;
for(int i = 0; i < n; i++) {
int x = read();
if(x == 1) ans++;
else if(x == 2) ans++;
}
cout << ans << endl;
}
return 0;
}
思路:
设f[i][j][k]表示:当前节点编号为i,下一步往j方向走(j=0为向左,j=1为向右),用了k次魔法获得的能量的最大值。
-
如果上一步是往右,这一步的下一步自然往左,有: f[tr[u].l][1][i] = f[u][0][i] + tr[l].w;
当i > 0时,如果上一步往左,则使用一次魔法时,这一步的下一步仍然往左,有: f[tr[u].l][0][i] = f[u][1][i-1] + tr[l].w; -
如果上一步是往左,这一步自然往右,有:f[tr[u].r][0][i] = f[u][1][i] + tr[r].w;
当i > 0时,如果上一步往右,则使用一次魔法时,这一步的下一步仍然往右,有:、
f[tr[u].r][1][i]= f[u][0][i-1] + tr[r].w;
在过程中维护最大值。
代码:
/*
qwq!
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <cmath>
#include <unordered_map>
using namespace std;
#define pb push_back
#define pu push
#define fi first
#define se second
#define LL long long
#define int long long
typedef pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
int f[N][2][310];
struct node {
int l = 0, r = 0, w;
}tr[N];
int n, m, mx, pos;
int read () {
int k=0,f=1;
char c=getchar ();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar ();}
while (c>='0'&&c<='9') {k=k*10+c-'0';c=getchar ();}
return k*f;
}
void dfs(int u) {
// 往左
if(tr[u].l) {
int l = tr[u].l;
for(int i = 0; i <= m; i++) {
f[l][1][i] = f[u][0][i] + tr[l].w;
if(i) {
f[l][0][i] = f[u][1][i-1] + tr[l].w;
if(!tr[l].l && !tr[l].r) {
int x = max(f[l][1][i], f[l][0][i]);
if(x > mx) {
mx = x;
pos = l;
}else if(x == mx) {
pos = min(pos, l);
}
}
}
}
dfs(l);
}
// 往右
if(tr[u].r) {
int r = tr[u].r;
for(int i = 0; i <= m; i++) {
f[r][0][i] = f[u][1][i] + tr[r].w;
if(i) {
f[r][1][i] = f[u][0][i-1] + tr[r].w;
if(!tr[r].l && !tr[r].r) {
int x = max(f[r][1][i], f[r][0][i]);
if(x > mx) {
mx = x;
pos = r;
}else if(x == mx) {
pos = min(pos, r);
}
}
}
}
dfs(r);
}
}
signed main() {
n = read(), m = read();
for(int i = 1; i <= n; i++) tr[i].w = read();
for(int i = 1; i < n; i++) {
int a = read(), b = read(), st = read();
if(st == 1) tr[a].l = b;
else tr[a].r = b;
}
mx = tr[1].w, pos = 1;
for(int i = 0; i <= m; i++) f[1][0][i] = f[1][1][i] = tr[1].w;
dfs(1);
cout << pos << endl << mx << endl;
return 0;
}
思路:
用st表存储每个区间的最大公约数,然后枚举左端点,二分右端点。
代码:
/*
qwq!
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <cmath>
#include <unordered_map>
using namespace std;
#define pb push_back
#define pu push
#define fi first
#define se second
#define LL long long
#pragma GCC optimize(2)
#define int long long
typedef pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 10;
int f[N][30];
int lg[N];
int n, m;
inline int read () {
int k=0,f=1;
char c=getchar ();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar ();}
while (c>='0'&&c<='9') {k=k*10+c-'0';c=getchar ();}
return k*f;
}
inline void write(int x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10-'0');
return;
}
inline int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
inline void Init() {
for(int j = 1; j < 30; j++)
for(int i = 1; i + (1 << j) - 1 <= n; i++) {
f[i][j] = gcd(f[i][j-1], f[i + (1 << j - 1)][j-1]);
}
}
inline int query(int l, int r) {
int k = lg[r - l + 1];
return gcd(f[l][k], f[r - (1 << k) + 1][k]);
}
signed main() {
int T = read();
lg[1] = 0;
for(int i = 2; i <= N; i++) lg[i] = lg[i>>1] + 1;
//for(int i = 1; i <= 10; i++) cout << lg[i] << endl;
//cout << endl;
//for(int i = 1; i <= 10; i++) cout << (int)(log(i) / log(2))<< endl;
while(T--) {
n = read(), m = read();
unordered_map<int,int>mp;
memset(f, 0, sizeof f);
for(int i = 1; i <= n; i++) f[i][0] = read();
Init();
for(int i = 1; i <= n; i++) {
int x = f[i][0];
int j = i;
while(j <= n) {
int l = j, r = n;
while(l < r) {
int mid = l + r + 1 >> 1;
if(query(i, mid) == x) l = mid;
else r = mid - 1;
}
mp[x] += l - j + 1;
j = l + 1;
x = query(i, j);
}
}
while(m--) {
int x = read();
printf("%lld\n", mp[x]);
}
}
return 0;
}