总结一下:菜是原罪。菜哭。
A. Captain Flint and Crew Recruitment
题意:
给你个n,让你把他拆分成4个数。其中至少三个数是伪素数。伪素数的定义是:两个素数的乘积。如:6 = 2 × 3,10 = 2 × 5。坑点:这四个数互不相等。
题解:
我们从小到大写几个伪素数:6、10、14、15、21…
最小为6+10+14 + 1 = 31。
所以n < 31,无解。
n >= 31 时,这时候要特判,36、40、44,n-30=6 or 10 or 14时,这时候你自己找一下就行了。
ACcode:
/*
* @Author: NEFU_马家沟老三
* @LastEditTime: 2020-07-31 15:13:58
* @CSDN blog: https://blog.csdn.net/acm_durante
* @E-mail: 1055323152@qq.com
* @ProbTitle:
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define lowbit(x) ((x) & -(x))
#define mem(a, b) memset(a, b, sizeof(a))
const double PI = acos(-1.0);
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
if (n < 31 )
cout << "NO\n";
else
{
cout << "YES\n";
if(n == 40)
cout << 6 << ' ' << 10 << ' ' << 21 << ' ' << 3 << endl;
else if (n == 44)
cout << 6 << ' ' << 7 << ' ' << 10 << ' ' << 21 << endl;
else if (n == 36)
cout << 5 << ' ' << 6 << ' ' << 10 << ' ' << 15 << endl;
else
cout << 14 << ' ' << 10 << ' ' << 6 << ' ' << n - 30 << endl;
}
}
return 0;
}
B. Captain Flint and a Long Voyage
题意:
给你个n,表示有n位数。将其每一位用二进制表示。如 x = 729,则k = 111 10 1001。现在将二进制表示的k的后n位擦去得到r,使r数最大。
若得到的数一样大,则输出x较小的内个。
题解:
我们首先只能从8、9中选取,因为这样得到的数最大。
8 : 1000、9 : 1001。
我们剩下的就是找规律:
n = 1 : x = 8 : k = 1000 : r = 100
n = 2 : x = 98 : k = 1001 1000 : r = 1001 10
n = 3 : x = 998 : k = 1001 1001 1000 : r = 1001 1001 1
n = 4 : x = 9998 :k = 1001 1001 1001 1000 : r = 1001 1001 1001
n = 5 : x = 99988 : k = 1001 1001 1001 1000 1000 : r = 1001 1001 1001 100
…
每4次是一次循环,8的个数是n/4向上取整。
/*
* @Author: NEFU_马家沟老三
* @LastEditTime: 2020-07-31 15:40:32
* @CSDN blog: https://blog.csdn.net/acm_durante
* @E-mail: 1055323152@qq.com
* @ProbTitle:
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define lowbit(x) ((x) & -(x))
#define mem(a, b) memset(a, b, sizeof(a))
const double PI = acos(-1.0);
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
int cnt_8 = (n + 3) / 4;
rep(i,1,n-cnt_8) cout << 9;
rep(i,1,cnt_8) cout << 8;
cout << endl;
}
return 0;
}
C. Uncle Bogdan and Country Happiness
题意:
一开始所有人都在城市1,然后每个人通过最短路回到自己的家,在回家的途中好心情可能会变差,但是坏心情不能变好。每个城市都有个心情测试器:他的数值h是 途经当前城市的人中 好心情的人数 - 坏心情的人数。
当每个人都回到家后,问你每个城市的心情测试器 测试的是否准确。当全部准确话输出“YES”,否则输出“NO”。
题解:
h = good - bad。
peoole = good + bad。
我们能得出good = ( h + people ) / 2
我们从城市1开始dfs树遍历,在遍历的时候通过上述公式计算出当前城市心情好的人数。分下列三种情况:
- people + h 不能被 2 整除,则NO
- 计算出的good满足:0<= good <= people
- 用公式计算出的good的人数 >= 子树心情好的人数
第三条:因为我们是递归向根传值,所以在这个逆向过程中,原本坏心情可以变成好心情。
ACcode:
/*
* @Author: NEFU_马家沟老三
* @LastEditTime: 2020-07-31 14:12:34
* @CSDN blog: https://blog.csdn.net/acm_durante
* @E-mail: 1055323152@qq.com
* @ProbTitle: dfs树遍历(补题)
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define lowbit(x) ((x) & -(x))
#define mem(a, b) memset(a, b, sizeof(a))
const double PI = acos(-1.0);
const ll mod = 1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
int t,n,m;
const int N = 2e5+5;
struct edge
{
int to,next;
}e[N];
int cnt;
int peo[100050],h[100050];
int pp[100050],good[100050];
int head[100050];
void add(int u,int v){
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
bool flag = 0;
void dfs(int now,int pre){
if(flag) return;
pp[now] = peo[now];
int sum_g = 0;
for(int i = head[now]; ~i ; i = e[i].next){
if(pre == e[i].to) continue;
dfs(e[i].to,now);
sum_g += good[e[i].to];
pp[now] += pp[e[i].to];
}
if((pp[now]+h[now])%2){ flag = 1;return;}
good[now] = (pp[now]+h[now]) >> 1;
if(good[now]<0||pp[now]<good[now]) {flag = 1;return;}
if(sum_g > good[now]) {flag = 1;return;}
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin >> t;
while (t--)
{
mem(head,-1),mem(e,0);
cnt = 0;
flag = 0;
cin >> n >> m;
rep(i,1,n) cin >> peo[i];
rep(i,1,n) cin >> h[i];
rep(i,1,n-1){
int x,y;
cin >> x >> y;
add(x,y),add(y,x);
}
dfs(1,-1);
cout << (flag?"NO":"YES") << endl;
}
return 0;
}
D. Captain Flint and Treasure
题意:
给你两个长度为n的序列a,b。
我们总共进行n次下列操作:
- 选择 位置 i
- 将 a[i] 加到 ans上
- 如果 b[i] != -1 ,则将 a[i] 加到 a[bi]上
输出ans的最大值和n次操作的顺序。
题解
我们根据b数组进行建树,如果b[i] != -1,则我们从 b[i] 到 i 建立一个有向边。
我们对每一课树进行遍历,并建立两个数组存放操作顺序。
如果a[i] >=0,我们则优先进行这次的操作存入到数组1中,因为他对他的根节点是做正贡献。
若a[i] < 0,我们则将这次操作放到根节点的后面,存放到数组2中,因为如果将他加到根节点的话,他做的是负贡献。最后将数组二倒序输出。
ACcode:
/*
* @Author: NEFU_马家沟老三
* @LastEditTime: 2020-07-31 16:17:45
* @CSDN blog: https://blog.csdn.net/acm_durante
* @E-mail: 1055323152@qq.com
* @ProbTitle: dfs树遍历(补题)
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
#define lowbit(x) ((x) & -(x))
#define mem(a, b) memset(a, b, sizeof(a))
const double PI = acos(-1.0);
const ll mod = 1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N = 2e5+5;
ll a[N],b[N];
int cnt = 0;
struct Edge
{
int to,next;
}e[N];
int head[N];
void add(int u,int v){
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
ll ans = 0;
vector<int>orede[2];
bool vis[N];
void dfs(int pos){
vis[pos] = 1;
for(int i = head[pos];~i;i = e[i].next){
if(!vis[e[i].to])
dfs(e[i].to);
}
ans+=a[pos];
if(a[pos]>0&&b[pos]!=-1)
a[b[pos]] += a[pos];
if(a[pos] > 0) orede[0].push_back(pos);
else orede[1].push_back(pos);
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int n;
mem(head,-1);
cin >> n;
rep(i,1,n) cin >> a[i];
rep(i,1,n) {
int x;
cin >> x;
if(x!=-1)
add(x,i);
b[i] = x;
}
rep(i,1,n){
if(vis[i]) continue;
dfs(i);
}
cout << ans << endl;
reverse(orede[1].begin(),orede[1].end());
for(auto &i : orede[0]) cout << i << ' ';
for(auto &i : orede[1]) cout << i << ' ';
cout << endl;
return 0;
}