ACM-ICPC 2018 南京赛区网络预赛 Solution
A. An Olympian Math Problem
cout << n - 1 << endl;
#include <bits/stdc++.h>
using namespace std; #define ll long long int t;
ll n; inline void Run()
{
scanf("%d", &t);
while (t--)
{
scanf("%lld", &n);
printf("%lld\n", n - );
}
} int main()
{
#ifdef LOCAL
freopen("Test.in", "r", stdin);
#endif Run(); return ;
}
B. The writing on the wall
题意:给出n * m的矩形,找出有多少个子矩形不包含黑块
思路:枚举每一个当右下角的情况,那么情况总数就是黑块构成的边界里面的格子数量,优先队列优化
#include <bits/stdc++.h>
using namespace std; #define ll long long
#define N 100010
#define M 110 int t, n, m, k;
int G[N][M];
int low[M]; struct node
{
ll h, num;
inline node() {}
inline node(ll h, ll num) : h(h), num(num) {}
inline bool operator < (const node &r) const
{
return h < r.h;
}
}; priority_queue <node> q; int main()
{
#ifdef LOCAL_JUDGE
freopen("Text.txt", "r", stdin);
#endif // LOCAL_JUDGE
scanf("%d", &t);
for (int kase = ; kase <= t; ++kase)
{
printf("Case #%d: ", kase);
memset(G, , sizeof G);
memset(low, , sizeof low);
while (!q.empty()) q.pop();
scanf("%d%d%d", &n, &m, &k);
for (int i = , x, y; i <= k; ++i)
{
scanf("%d%d", &x, &y);
G[x][y] = ;
}
ll ans = , sum = ;
for (int i = ; i <= n; ++i)
{
for (int j = ; j <= m; ++j)
{
//if (i % 1000 == 0) cout << i << endl;
if (G[i][j] == )
{
while (!q.empty()) q.pop();
sum = ;
low[j] = i;
continue;
}
if (j == )
{
while (!q.empty()) q.pop();
sum = ;
}
ll H = i - low[j];
ll num = ;
while (!q.empty() && q.top().h > H)
{
num += q.top().num;
sum -= q.top().h * q.top().num;
q.pop();
}
sum += num * H;
ans += sum;
q.emplace(H, num);
}
}
printf("%lld\n", ans);
}
return ;
}
C. GDY
按题意模拟即可,注意细节
#include <bits/stdc++.h>
using namespace std; int Move[] = { , , , , , , , , , , , , , }; struct DT
{
int num[], cnt;
int score;
inline DT()
{
score = ; cnt = ;
memset(num, , sizeof num);
}
inline void Get()
{
for (int i = ; i <= ; ++i)
score += num[i] * i;
}
}arr[]; int t, n, m;
queue <int> q; inline void work()
{
int turn = , pre = -, tot = , nx;
for (int i = ; i < ; ++i) if (arr[].num[Move[i]])
{
pre = Move[i];
--arr[].num[Move[i]];
--arr[].cnt;
break;
}
while (true)
{
turn = turn % n + ;
if (tot == n - )
{
for (int i = turn; i <= n; ++i) if (!q.empty())
{
++arr[i].cnt;
++arr[i].num[q.front()]; q.pop();
}
for (int i = ; i < turn; ++i) if (!q.empty())
{
++arr[i].cnt;
++arr[i].num[q.front()]; q.pop();
}
for (int i = ; i < ; ++i) if (arr[turn].num[Move[i]])
{
--arr[turn].num[Move[i]];
if (--arr[turn].cnt == ) return;
pre = Move[i]; tot = ;
break;
}
}
else if (pre == ) tot++;
else
{
if (pre == ) nx = ;
else nx = pre + ;
if (arr[turn].num[nx])
{
--arr[turn].num[nx];
if (--arr[turn].cnt == ) return;
pre = nx; tot = ;
}
else
{
if (arr[turn].num[])
{
--arr[turn].num[];
if (--arr[turn].cnt == ) return;
pre = ; tot = ;
}
else tot++;
}
}
}
} inline void Run()
{
scanf("%d", &t);
for (int kase = ; kase <= t; ++kase)
{
while (!q.empty()) q.pop();
printf("Case #%d:\n", kase);
scanf("%d%d", &n, &m);
for (int i = , u; i <= m; ++i)
{
scanf("%d", &u);
q.emplace(u);
}
for (int i = ; i <= n; ++i)
{
arr[i] = DT();
for (int j = ; j <= ; ++j)
{
if (!q.empty())
{
arr[i].num[q.front()]++; q.pop();
++arr[i].cnt;
}
}
}
work();
for (int i = ; i <= n; ++i)
{
arr[i].Get();
if (arr[i].score == ) puts("Winner");
else printf("%d\n", arr[i].score);
}
}
} int main()
{
#ifdef LOCAL
freopen("Test.in", "r", stdin);
#endif Run();
return ;
}
D. Jerome's House
留坑。
E. AC Challenge
题意:有n道题目,每次提交得到分数$t * a_i + b_i$ 有一些题目的提交必须要某些题目提交之后才能提交,求最后获得的最大分数
思路:记忆化搜索,二进制标记状态 或者 状压DP
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[ << ];
int n;
struct node {
ll ai, bi;
int state;
inline node(){}
inline node(ll ai, ll bi, int state):ai(ai),bi(bi), state(state){}
}arr[];
inline ll DFS(int t, int S)
{
if (t > n) return ;
if (dp[S] != -) return dp[S];
ll res = ;
for (int i = ; i < n; ++i)
{
int tmp = << i;
if ((tmp & S) == )
{
if ((S & arr[i].state) != arr[i].state) continue;
res = max(res, t * arr[i].ai + arr[i].bi + DFS(t + , (S | tmp)));
}
}
dp[S] = res;
return res;
}
inline void RUN()
{
while (~scanf("%d", &n))
{
memset(dp, -, sizeof dp);
for (int i = ; i < n; ++i)
{
int m;
int S = ;
scanf("%lld %lld %d", &arr[i].ai, &arr[i].bi, &m);
while (m--)
{
int tmp = ;
scanf("%d", &tmp);
S += ( << (tmp - ));
}
arr[i].state = S;
}
ll ans = DFS(, );
printf("%lld\n", ans);
}
}
int main()
{
#ifdef LOCAL_JUDGE
freopen("Text.txt", "r", stdin);
#endif // LOCAL_JUDGE
RUN();
#ifdef LOCAL_JUDGE
fclose(stdin);
#endif // LOCAL_JUDGE
return ;
}
#include <bits/stdc++.h>
using namespace std; #define N (1 << 21)
#define ll long long struct node
{
ll a, b;
int sta;
inline void scan()
{
int tot, k; sta = ;
scanf("%lld%lld%d", &a, &b, &tot);
while (tot--)
{
scanf("%d", &k);
sta |= ( << (k - ));
}
}
}arr[]; int n;
ll dp[N]; inline ll Count(int x)
{
int res = ;
while (x)
{
++res;
x &= (x - );
}
return res;
} inline void Run()
{
while (scanf("%d", &n) != EOF)
{
for (int i = ; i <= n; ++i) arr[i].scan();
memset(dp, -, sizeof dp);
ll ans = ; dp[] = ;
for (int i = ; i < ( << n); ++i)
{
if (dp[i] == -) continue;
for (int j = ; j <= n; ++j)
{
if (!(i & ( << (j - ))) && (i & (arr[j].sta)) == arr[j].sta)
{
int tmp = i | ( << (j - ));
ll t = Count(tmp);
dp[tmp] = max(dp[tmp], dp[i] + arr[j].a * t + arr[j].b);
ans = max(ans, dp[tmp]);
}
}
}
printf("%lld\n", ans);
}
} int main()
{
#ifdef LOCAL
freopen("Test.in", "r", stdin);
#endif Run();
return ;
}
F. An Easy Problem On The Trees
留坑。
G. Lpl and Energy-saving Lamps
题意:有n个房间,每次按顺序换灯泡,一个房间要不所有灯泡都换,要不一个都不换,每个月有固定的新灯泡数,没还完留到下个月,询问第几个月能够换掉几个房间以及剩下的房间数
思路:线段树维护一个最小值,预处理答案
#include <bits/stdc++.h>
using namespace std; #define N 100010
#define INF 0x3f3f3f3f
#define ll long long typedef pair <int, int> pii; int n, m, q, sum;
int arr[N];
pii ans[N]; struct node
{
int l, r, cnt;
int Min, sum;
inline node() {}
inline node(int _l, int _r)
{
l = _l, r = _r;
Min = sum = ;
}
}tree[N << ]; inline void pushup(int id)
{
tree[id].Min = min(tree[id << ].Min, tree[id << | ].Min);
tree[id].sum = tree[id << ].sum + tree[id << | ].sum;
tree[id].cnt = tree[id << ].cnt + tree[id << | ].cnt;
} inline void build(int id, int l, int r)
{
tree[id] = node(l, r);
if (l == r)
{
tree[id].Min = tree[id].sum = arr[l];
tree[id].cnt = ;
return;
}
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
pushup(id);
} int anssum, remind; inline void query(int id)
{
if (tree[id].Min <= remind && tree[id].sum <= remind)
{
anssum += tree[id].cnt;
sum -= tree[id].sum;
remind -= tree[id].sum;
tree[id].Min = INF;
tree[id].sum = ;
tree[id].cnt = ;
return;
}
if (tree[id << ].Min <= remind) query(id << );
if (tree[id << | ].Min <= remind) query(id << | );
pushup(id);
} inline void out(int x)
{
if (x / ) out(x / );
putchar(x % + '');
} inline void Run()
{
while (scanf("%d%d", &n, &m) != EOF)
{
memset(ans, , sizeof ans); sum = ;
for (int i = ; i <= n; ++i) scanf("%d", arr + i), sum += arr[i];
build(, , n); remind = m;
for (int i = ; i <= ; ++i, remind += m)
{
if (sum == )
{
ans[i] = ans[i - ];
continue;
}
anssum = ; query();
ans[i].first = ans[i - ].first + anssum;
ans[i].second = remind;
}
scanf("%d", &q);
for (int i = , x; i <= q; ++i)
{
scanf("%d", &x);
out(ans[x].first); putchar(' ');
out(ans[x].second); putchar('\n');
}
}
} int main()
{
#ifdef LOCAL
freopen("Test.in", "r", stdin);
#endif Run();
return ;
}
H. Set
留坑。
I. Skr
留坑。
J. Sum
题意:定义$F[n] = 有多少个n = ab$ a 和 b 都不能是平方数的倍数 1 除外 求 $\sum_{i = 1} ^ {i = n} F[n]$
思路:枚举每个素数,对于拥有不同质因子的数,权值成2,对于拥有两个相同的质因子的数,权值除以2,对于拥有三个或者三个以上质因子的数,权值为零,最后求和。(卡常)
#include <bits/stdc++.h>
using namespace std; typedef long long ll;
const int maxn = 2e7 + ; int n;
int tot;
int isprime[maxn];
int prime[maxn];
int a[maxn];
int ans[maxn]; inline void Init_prime()
{
tot = ;
prime[] = ;
a[] = ;
ans[] = ;
for (register int i = ; i < maxn; ++i)
{
a[i] = ;
if (!isprime[i])
{
prime[tot++] = i; }
for (register int j = ; j < tot && i * prime[j] < maxn; ++j)
{
isprime[i * prime[j]] = ;
if (!(i % prime[j]))
{
break;
}
}
}
for (register int i = ; i < tot; ++i)
{
for (register int j = ; j * prime[i] < maxn; ++j)
{
a[j * prime[i]] <<= ;
}
if (prime[i] > maxn / prime[i]) continue;
for (register int j = ; j * prime[i] * prime[i] < maxn; ++j)
{
if (j % prime[i] == )
{
a[j * prime[i] * prime[i]] = ;
}
a[j * prime[i] * prime[i]] >>= ;
}
}
for (register int i = ; i < maxn; ++i)
{
ans[i] = ans[i - ] + a[i];
}
} int main()
{
Init_prime();
int t;
//cout << tot << endl;
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
printf("%d\n", ans[n]);
}
return ;
}
K. The Great Nim Game
留坑。
L. Magical Girl Haze
题意:有n个城市,m条边,可以令k条路权值为0,求1 - n 的最短路
思路:对于每个城市,枚举到这个城市,免费0-k次的权值,跑一个(立体的?)最短路
#include <bits/stdc++.h>
using namespace std; #define N 100010
#define ll long long
#define INFLL 0x3f3f3f3f3f3f3f3f struct Edge
{
int to, nx; ll w;
inline Edge() {}
inline Edge(int to, int nx, ll w) : to(to), nx(nx), w(w) {}
}edge[N << ]; int head[N], pos; inline void Init()
{
memset(head, -, sizeof head);
pos = ;
} inline void addedge(int u, int v, ll w)
{
edge[++pos] = Edge(v, head[u], w); head[u] = pos;
} struct node
{
int to, p; ll w;
inline node() {}
inline node(int to, int p, ll w) : to(to), p(p), w(w) {}
inline bool operator < (const node &r) const
{
return w > r.w;
}
}; ll dist[N][];
bool used[N][];
int t, n, m, k; inline void Dijkstra()
{
for (int i = ; i <= n; ++i) for (int j = ; j <= k; ++j) dist[i][j] = INFLL, used[i][j] = false;
priority_queue <node> q; q.emplace(, , ); dist[][] = ;
while (!q.empty())
{
int u = q.top().to;
int p = q.top().p;
ll w = q.top().w;
//cout << w << endl;
q.pop();
if (used[u][p]) continue;
used[u][p] = true;
dist[u][p] = w;
for (int i = head[u]; ~i; i = edge[i].nx)
{
int v = edge[i].to;
ll c = edge[i].w;
if (dist[u][p] + c < dist[v][p])
{
dist[v][p] = dist[u][p] + c;
q.emplace(v, p, dist[v][p]);
}
if (p + <= k && dist[u][p] < dist[v][p + ])
{
dist[v][p + ] = dist[u][p];
q.emplace(v, p + , dist[v][p + ]);
}
}
}
} inline void Run()
{
scanf("%d", &t);
while (t--)
{
Init();
scanf("%d%d%d", &n, &m, &k);
int u, v; ll w;
for (int i = ; i <= m; ++i)
{
scanf("%d%d%lld", &u, &v, &w);
addedge(u, v, w);
}
Dijkstra();
ll ans = dist[n][k];
printf("%lld\n", ans);
}
}
int main()
{
#ifdef LOCAL
freopen("Test.in", "r", stdin);
#endif Run(); return ;
}
ACM-ICPC 2018 南京赛区网络预赛 Solution的更多相关文章
- ACM-ICPC 2018 南京赛区网络预赛 E题
ACM-ICPC 2018 南京赛区网络预赛 E题 题目链接: https://nanti.jisuanke.com/t/30994 Dlsj is competing in a contest wi ...
- ACM-ICPC 2018 南京赛区网络预赛
轻轻松松也能拿到区域赛名额,CCPC真的好难 An Olympian Math Problem 问答 只看题面 54.76% 1000ms 65536K Alice, a student of g ...
- ACM-ICPC 2018 南京赛区网络预赛 J.sum
A square-free integer is an integer which is indivisible by any square number except 11. For example ...
- ACM-ICPC 2018 南京赛区网络预赛B
题目链接:https://nanti.jisuanke.com/t/30991 Feeling hungry, a cute hamster decides to order some take-aw ...
- 计蒜客 30999.Sum-筛无平方因数的数 (ACM-ICPC 2018 南京赛区网络预赛 J)
J. Sum 26.87% 1000ms 512000K A square-free integer is an integer which is indivisible by any squar ...
- 计蒜客 30996.Lpl and Energy-saving Lamps-线段树(区间满足条件最靠左的值) (ACM-ICPC 2018 南京赛区网络预赛 G)
G. Lpl and Energy-saving Lamps 42.07% 1000ms 65536K During tea-drinking, princess, amongst other t ...
- 计蒜客 30990.An Olympian Math Problem-数学公式题 (ACM-ICPC 2018 南京赛区网络预赛 A)
A. An Olympian Math Problem 54.28% 1000ms 65536K Alice, a student of grade 66, is thinking about a ...
- ACM-ICPC 2018 南京赛区网络预赛 B. The writing on the wall
题目链接:https://nanti.jisuanke.com/t/30991 2000ms 262144K Feeling hungry, a cute hamster decides to o ...
- ACM-ICPC 2018 南京赛区网络预赛 L. Magical Girl Haze
262144K There are NN cities in the country, and MM directional roads from uu to v(1\le u, v\le n)v ...
随机推荐
- 织梦移动版页面点击下一篇获取不到id
1.首先找到网站目录下面的/include/arc.archives.class.php文件 2.找到837行的如下内容 if ( defined('DEDEMOB') ) { $mlink = 'v ...
- [hbase] hbase 基础使用
一.准备 hadoop 2.8.0 (提前配置好) hbase 1.2.6 zookeeper 3.4.9 (配置完成) jdk1.8 hadoop 集群信息: zk集群: 二.安装配置 1.下载(官 ...
- Win2008R2+Apache+PHP+Tomcat配置
一.VC运行库 对于Apache和PHP,在Windows上运行的话都需要对应VC运行库的支持,即Apache.PHP和VC运行库这三者的版本必须相对应,这就会带来很多问题,比如下了较新的Apache ...
- GPRS模块在Linux平台上ppp拨号上网总结与心得
linux平台的ppp拨号上网,(注明:这里只谈命令行拨号,用linux就要习惯和熟练使用命令行) 在网上常见的有三种方式:1.使用智能的ppp拨号软件wvdial:参考案例:本博客的<使用wv ...
- LostRoutes项目日志——玩家飞机精灵Fighter解析
Fighter类的定义在Fighter.js中,Fighter类继承与PhysicsSprite. 原版的Fighter.js: var Fighter = cc.PhysicsSprite.exte ...
- php冒泡排序详解笔记
冒泡 /* * 冒泡排序(从小到大) * 介绍: * 它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来. * 思路: * 比较相邻的元素.如果第一个比第二个大,就交换他 ...
- cs231n(三) 误差反向传播
摘要 本节将对反向传播进行直观的理解.反向传播是利用链式法则递归计算表达式的梯度的方法.理解反向传播过程及其精妙之处,对于理解.实现.设计和调试神经网络非常关键.反向求导的核心问题是:给定函数 $f( ...
- Solve Error: nafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new[](unsigned int)" (??_U@YAPAXI@Z) already defined in libcpmt.lib(newaop.obj)
Error: nafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new[](unsigned int)&quo ...
- Linux手动添加swap分区
转自:https://blog.csdn.net/whatday/article/details/51024571 为什么需要swap 根据Redhat公司的建议,Linux系统swap分区最适合的大 ...
- python全栈开发 * 23 面向对象 知识点汇总 * 180704
23 面向对象 -----特殊方法 1. isinstance(obj,类名) 判断对象是否是此类实例化或者此类的子类实例化出来的class A:passclass B(A):passb1=B()pr ...