牛客假日团队赛8
A Cell Phone Network
-
思路:最小支配集
-
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
ll Pow_mod(ll a, ll b, ll c){
ll ans = 1;
a %= c;
while (b){
if (b & 1) ans = (ans * a) % c;
a = (a * a) % c;
b >>= 1;
}
return (ans % c);
}
ll Pow(ll a, ll b){
ll ans = 1;
while (b){
if (b & 1) ans *= a;
a *= a;
b >>= 1;
}
return ans;
}
int gcd(int a, int b){
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b){
return a * 1ll / gcd(a, b) * b;
}
const int N = 10010;
int p[N]; // 父节点编号
bool vis[N]; // dfs判重
int newpos[N]; // newpos[i]表示dfs序列的第i个点是哪个点
int now; // 表示dfs序列已有点数
bool s[N]; // 判断是否被覆盖
bool se[N]; // se[i]表示点i属于要求的集合
int head[N];
int n, u, v, ans, tot;
struct node{
int to, next;
}edge[N << 1];
void dfs(int x){
newpos[++ now] = x;
for (int i = head[x]; i; i = edge[i].next){
if (!vis[edge[i].to]){
vis[edge[i].to] = true;
p[edge[i].to] = x;
dfs(edge[i].to);
}
}
}
void greedy(){
for (int i = n; i >= 1; i -- ){
int t = newpos[i];
if (!s[t]){
if (!se[p[t]]){
se[p[t]] = true;
ans ++;
}
s[t] = true;
s[p[t]] = true;
s[p[p[t]]] = true;
}
}
}
void add_edge(int u, int v){
edge[++ tot].to = v;
edge[tot].next = head[u];
head[u] = tot;
}
int main(){
scanf("%d", &n);
for (int i = 1; i < n; i ++ ){
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
p[1] = 1, vis[1] = 1,
dfs(1);
greedy();
printf("%d
", ans);
return 0;
}
B iCow
-
思路:模拟 题意明确 按着题目分配就行了
-
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
ll Pow_mod(ll a, ll b, ll c){
ll ans = 1;
a %= c;
while (b){
if (b & 1) ans = (ans * a) % c;
a = (a * a) % c;
b >>= 1;
}
return (ans % c);
}
ll Pow(ll a, ll b){
ll ans = 1;
while (b){
if (b & 1) ans *= a;
a *= a;
b >>= 1;
}
return ans;
}
int gcd(int a, int b){
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b){
return a * 1ll / gcd(a, b) * b;
}
const int N = 1010;
int n, t, maxr, pos_, divi, rem;
struct cow{
int r, pos;
}cows[N];
int main(){
scanf("%d%d", &n, &t);
for (int i = 1; i <= n; i ++ ){
scanf("%d", &cows[i].r);
cows[i].pos = i;
}
while (t -- ){
maxr = 0;
pos_ = 0;
for (int i = 1; i <= n; i ++ ){
if (cows[i].r > maxr){
maxr = cows[i].r;
pos_ = cows[i].pos;
}
}
cows[pos_].r = 0;
divi = maxr / (n - 1);
rem = maxr % (n - 1);
printf("%d
", pos_);
for (int i = 1; i <= n; i ++ ){
if (i == pos_) continue;
cows[i].r += divi;
}
for (int i = 1; i <= rem; i ++ ){
if (i == pos_) rem ++;
else cows[i].r += 1;
}
}
return 0;
}
C 阶乘之和
-
思路:直接用python过的
-
AC代码
n = input()
n = int(n)
fact = 1
sum = 0
i = 1
while n >= i:
fact = fact * i
sum = sum + fact
i = i + 1
print(sum)
D Artificial Lake
-
思路:模拟(队友写的
-
AC代码
#include <bits/stdc++.h>
#include <iostream>
#include <cstring>
#include <stack>
#include <cstdlib>
#include <queue>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
#include <list>
#include <iterator>
#include <set>
#include <map>
#include <utility>
#include <iomanip>
#include <ctime>
#include <sstream>
#include <bitset>
#include <deque>
#include <limits>
#include <numeric>
#include <functional>
#define gc getchar()
#define mem(a) memset(a,0,sizeof(a))
#define mod 1000000007
#define sort(a,n,int) sort(a,a+n,less<int>())
#define fread() freopen("in.in","r",stdin)
#define fwrite() freopen("out.out","w",stdout)
#define PI acos(-1.0)
#define N 100005
#define MOD 2520
#define E 1e-12
typedef long long ll;
typedef char ch;
typedef double db;
const long long INF = 0x3f3f3f3f3f3f3f3f;
using namespace std;
struct node
{
ll w , h;
int l , r;
}a[N];
int n = 0;
long long res[N] = {0};
int lowest()
{
ll minv = INF , pos = 0;
for(int i = 1;i <= n;i++)
if(a[i].h < minv)
{
minv = a[i].h;
pos = i;
}
return pos;
}
int update(int position)
{
for(int i = 0;i<n;i++)
{
int left = a[position].l , right = a[position].r;
if(a[left].h < a[position].h)
position = left;
else if(a[right].h < a[position].h)
position = right;
else
return position;
}
}
void guanshui(int position)
{
int counter = 1;
long long sum = 0;
while(counter <= N)
{
counter++;
sum += a[position].w;
res[position] = sum;
int l = a[position].l , r = a[position].r;
sum += (min(a[l].h , a[r].h) - a[position].h - 1) * a[position].w;
a[l].r = r;
a[r].l = l;
if(a[l].h < a[r].h)
{
a[l].w += a[position].w;
position = l;
}
else
{
a[r].w += a[position].w;
position = r;
}
position = update(position);
}
}
int main()
{
cin >> n;
int position = 0;
for(int i = 1;i <= n;i++)
{
cin >> a[i].w >> a[i].h;
}
for(int i = 0;i <= n+1;i++)
{
a[i].l = i-1;
a[i].r = i+1;
}
a[0].w = 1;
a[0].h = INF;
a[n+1].w = 1;
a[n+1].h = INF;
position = lowest();
guanshui(position);
for(int i = 1;i <= n;i++)
{
cout << res[i] << endl;
}
return 0;
}
E Haybale Guessing
-
思路:并查集+区间染色
-
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
ll Pow_mod(ll a, ll b, ll c){
ll ans = 1;
a %= c;
while (b){
if (b & 1) ans = (ans * a) % c;
a = (a * a) % c;
b >>= 1;
}
return (ans % c);
}
ll Pow(ll a, ll b){
ll ans = 1;
while (b){
if (b & 1) ans *= a;
a *= a;
b >>= 1;
}
return ans;
}
int gcd(int a, int b){
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b){
return a * 1ll / gcd(a, b) * b;
}
const int N = 1e6 + 10;
int n, q, ans;
int prt[N]; // prt[i] = j 表示区间 [j + 1, i] 被覆盖
int fa[N];
struct node_{
int l, r, A;
}seg[N];
bool cmp(int a, int b){
if (seg[a].A == seg[b].A){
if (seg[a].l == seg[b].l) return seg[a].r < seg[b].r;
return seg[a].l < seg[b].l;
}
return seg[a].A > seg[b].A;
}
int find(int x){
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
bool judge(int mid){
for (int i = 1; i <= mid; i ++ ) prt[i] = i;
for (int i = 1; i <= n; i ++ ) fa[i] = i;
sort(prt + 1, prt + mid + 1, cmp);
for (int i = 1; i <= mid; i ++ ){
int A = seg[prt[i]].A;
int l = seg[prt[i]].l, r = seg[prt[i]].r, L = l, R = r; // [l, r]为交集 [L, R]为并集
while (i + 1 <= mid && A == seg[prt[i + 1]].A){
++ i;
if (seg[prt[i]].l > r) return false;
l = max(l, seg[prt[i]].l);
r = min(r, seg[prt[i]].r);
L = min(L, seg[prt[i]].l);
R = max(R, seg[prt[i]].r);
}
int x = find(l), y = find(r);
if ((l != r && x == y && y != r) || (l == r && y != r)) return false;
x = L, y = R;
int flag = find(y + 1);
while (flag != find(x)){
int find_x = find(x);
fa[find_x] = fa[find_x + 1];
}
}
return true;
}
int main(){
scanf("%d%d", &n, &q);
for (int i = 1; i <= q; i ++ )
scanf("%d%d%d", &seg[i].l, &seg[i].r, &seg[i].A);
int l = 1, r = q + 1;
while (r - l > 1){
int mid = (l + r) >> 1;
if (judge(mid))
l = mid;
else
r = mid;
}
if (l == q) ans = 0;
else ans = l + 1;
printf("%d
", ans);
return 0;
}
F Telephone Lines
-
思路:最短路 spfa+二分
-
AC代码
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
ll Pow_mod(ll a, ll b, ll c){
ll ans = 1;
a %= c;
while (b){
if (b & 1) ans = (ans * a) % c;
a = (a * a) % c;
b >>= 1;
}
return (ans % c);
}
ll Pow(ll a, ll b){
ll ans = 1;
while (b){
if (b & 1) ans *= a;
a *= a;
b >>= 1;
}
return ans;
}
int gcd(int a, int b){
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b){
return a * 1ll / gcd(a, b) * b;
}
const int N = 1010;
queue<int> q;
int n, p, k, tot, u, v, w, l, r, mid, ans;
int head[N], dist[N];
bool vis[N];
struct node{
int to, w, next;
}edge[N << 5];
inline void add_edge(int u, int v, int w){
edge[++ tot].to = v;
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot;
}
inline bool spfa(ll x){
memset(dist, 0x3f, sizeof(dist));
memset(vis, false, sizeof(vis));
dist[1] = 0;
vis[1] = true;
q.push(1);
while (!q.empty()){
int u = q.front();
q.pop();
vis[u] = false;
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
if (dist[v] > dist[u] + (edge[i].w > x ? 1 : 0)){
dist[v] = dist[u] + (edge[i].w > x ? 1 : 0);
if (!vis[v]){
vis[v] = true;
q.push(v);
}
}
}
}
return dist[n] <= k;
}
int main(){
l = 0, r = 0;
ans = -1;
scanf("%d%d%d", &n, &p, &k);
for (int i = 1; i <= p; i ++ ){
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w);
add_edge(v, u, w);
r = max(r, w);
}
while (l <= r){
mid = (l + r) >> 1;
if (spfa(mid)){
ans = mid;
r = mid - 1;
}
else l = mid + 1;
}
printf("%d
", ans);
return 0;
}
G Election Time
-
思路:排两次序就出来了
-
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
ll Pow_mod(ll a, ll b, ll c){
ll ans = 1;
a %= c;
while (b){
if (b & 1) ans = (ans * a) % c;
a = (a * a) % c;
b >>= 1;
}
return (ans % c);
}
ll Pow(ll a, ll b){
ll ans = 1;
while (b){
if (b & 1) ans *= a;
a *= a;
b >>= 1;
}
return ans;
}
int gcd(int a, int b){
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b){
return a * 1ll / gcd(a, b) * b;
}
const int N = 500010;
int n, k;
struct cow{
int pos, a, b;
}cows[N];
int cmp1(cow x, cow y){
return x.a > y.a;
}
int cmp2(cow x, cow y){
return x.b > y.b;
}
int main(){
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i ++ ){
scanf("%d%d", &cows[i].a, &cows[i].b);
cows[i].pos = i;
}
sort(cows + 1, cows + n + 1, cmp1);
sort(cows + 1, cows + k + 1, cmp2);
printf("%d
", cows[1].pos);
return 0;
}
H Costume Party
-
思路:数据很水 可以直接暴力过 可以二分或状态压缩
-
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
ll Pow_mod(ll a, ll b, ll c){
ll ans = 1;
a %= c;
while (b){
if (b & 1) ans = (ans * a) % c;
a = (a * a) % c;
b >>= 1;
}
return (ans % c);
}
ll Pow(ll a, ll b){
ll ans = 1;
while (b){
if (b & 1) ans *= a;
a *= a;
b >>= 1;
}
return ans;
}
int gcd(int a, int b){
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b){
return a * 1ll / gcd(a, b) * b;
}
const int N = 20010;
int n, s, cnt, ans;
int L[N];
int main(){
scanf("%d%d", &n, &s);
for (int i = 1; i <= n; i ++ ) scanf("%d", &L[i]);
sort(L + 1, L + n + 1);
for (int i = 1; i <= n; i ++ ){
while (cnt + 1 < i && L[i] + L[cnt + 1] <= s) cnt ++;
while (cnt >= 1 && L[i] + L[cnt] > s) cnt --;
ans += cnt;
}
printf("%d
", ans);
return 0;
}
I Cantor表
-
思路:模拟
-
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
ll Pow_mod(ll a, ll b, ll c){
ll ans = 1;
a %= c;
while (b){
if (b & 1) ans = (ans * a) % c;
a = (a * a) % c;
b >>= 1;
}
return (ans % c);
}
int gcd(int a, int b){
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b){
return a * 1ll / gcd(a, b) * b;
}
int n, k, s;
int main(){
scanf("%d", &n);
while (s < n){
k ++;
s += k;
}
if (k & 1) printf("%d/%d
", s - n + 1, n + k - s);
else printf("%d/%d
", n + k - s, s - n + 1);
return 0;
}
J Running
-
思路:dp
-
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
ll Pow_mod(ll a, ll b, ll c){
ll ans = 1;
a %= c;
while (b){
if (b & 1) ans = (ans * a) % c;
a = (a * a) % c;
b >>= 1;
}
return (ans % c);
}
ll Pow(ll a, ll b){
ll ans = 1;
while (b){
if (b & 1) ans *= a;
a *= a;
b >>= 1;
}
return ans;
}
int gcd(int a, int b){
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b){
return a * 1ll / gcd(a, b) * b;
}
const int N = 20010;
const int M = 510;
int n, m, ans;
int dp[N][M], d[N];
int main(){
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++ ) scanf("%d", &d[i]);
dp[1][1] = d[1];
for (int i = 1; i <= n; i ++ ){
for (int j = 0; j <= min(m, i); j ++ ){
if (j == 0) dp[i][0] = max(dp[i][0], dp[i - 1][0]);
else dp[i + j][0] = max(dp[i + j][0], dp[i][j]); // 休息
dp[i + 1][j + 1] = max(dp[i + 1][j + 1], dp[i][j] + d[i + 1]); // 不休息
}
}
// for (int i = 0; i <= m; i ++ )
// printf("%d
", dp[n][i]);
ans = dp[n][0];
printf("%d
", ans);
return 0;
}
K Cow Contest
-
思路:传递闭包 floyd就行
-
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
ll Pow_mod(ll a, ll b, ll c){
ll ans = 1;
a %= c;
while (b){
if (b & 1) ans = (ans * a) % c;
a = (a * a) % c;
b >>= 1;
}
return (ans % c);
}
ll Pow(ll a, ll b){
ll ans = 1;
while (b){
if (b & 1) ans *= a;
a *= a;
b >>= 1;
}
return ans;
}
int gcd(int a, int b){
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b){
return a * 1ll / gcd(a, b) * b;
}
const int N = 110;
const int M = 4510;
int n, m, u, v, cnt, ans;
int mp[N][N];
int main(){
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i ++ ){
scanf("%d%d", &u, &v);
mp[u][v] = 1;
}
for (int k = 1; k <= n; k ++ )
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
mp[i][j] = mp[i][j] || (mp[i][k] && mp[k][j]);
for (int i = 1; i <= n; i ++ ){
cnt = 0;
for (int j = 1; j <= n; j ++ )
if (mp[i][j] || mp[j][i])
cnt ++;
if (cnt == n - 1) ans ++;
}
printf("%d
", ans);
return 0;
}
L 幂次方
-
思路:模拟
-
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
ll Pow_mod(ll a, ll b, ll c){
ll ans = 1;
a %= c;
while (b){
if (b & 1) ans = (ans * a) % c;
a = (a * a) % c;
b >>= 1;
}
return (ans % c);
}
ll Pow(ll a, ll b){
ll ans = 1;
while (b){
if (b & 1) ans *= a;
a *= a;
b >>= 1;
}
return ans;
}
int gcd(int a, int b){
return b ? gcd(b, a % b) : a;
}
int lcm(int a, int b){
return a * 1ll / gcd(a, b) * b;
}
int n;
bool flag;
string s[16]={"2(0)", "2", "2(2)", "2(2+2(0))",
"2(2(2))", "2(2(2)+2(0))", "2(2(2)+2)", "2(2(2)+2+2(0))",
"2(2(2+2(0)))", "2(2(2+2(0))+1)", "2(2(2+2(0))+2)", "2(2(2+2(0))+2+2(0))",
"2(2(2+2(0))+2(2))", "2(2(2+2(0))+2(2)+2(0))", "2(2(2+2(0))+2(2)+2)", "2(2(2+2(0))+2(2)+2+2(0))"};
int main(){
scanf("%d", &n);
for (int i = 15; i >= 0; i -- ){
if (Pow(2, i) <= n){
n -= Pow(2, i);
if (flag) printf("+");
cout<<s[i];
flag = true;
}
}
return 0;
}