北京信息科技大学校赛 题解 | AK记录贴
比赛链接:https://ac.nowcoder.com/acm/contest/940#question
花了一天时间全部解决,题目不难,全是基础题+模板题。
A - kotori和糖果
链接:https://ac.nowcoder.com/acm/contest/940/A
题目描述
kotori共有n块糖果,每块糖果的初始状态是分散的,她想把这些糖果聚在一堆。但她每次只能把两堆糖果合并成一堆。
已知把两堆数量为a和b的糖果聚在一堆的代价是|a-b|。
kotori想知道,她把这n块糖果聚在一堆的最小代价是多少?
解题思路
直接贪心+搜索,复杂度O(n),可以解决1e6以内的查询。
对于1e6~1e18区间内的,还是用搜索。由于搜索过程中,奇数偶数的情况大约各一半,搜索分支数不会超过2^logn,具体是多少我也不知道。。。
先用迭代预处理1e6以内的,对剩下的进行记忆化搜索。
AC代码
#include<iostream>
using namespace std; typedef long long ll;
const int maxn = ; ll ans[maxn];
void init() {
ans[] = ;
ans[] = ;
ans[] = ;
for(int i=;i<maxn;i++) {
if(i&)
ans[i] = ans[i/] + ans[i/+] + ;
else
ans[i] = *ans[i/];
}
} ll dfs(ll n) {
if(n==) return ;
if(n==) return ; if(n<maxn) return ans[n];
if(n&) return dfs(n/) + dfs(n/+)+;
else return *dfs(n/);
} int main() {
init(); int T; cin>>T;
ll n;
while(T--){
scanf("%lld", &n);
printf("%lld\n", dfs(n));
}
return ;
}
B - kotori和气球
链接:https://ac.nowcoder.com/acm/contest/940/B
题目描述
kotori最近迷上了摆气球的游戏。她一共有n种气球,每种气球有无数个。她要拿出若干个气球摆成一排。
但是,由于气球被施放了魔法,同样种类的气球如果相邻会发生爆炸,因此若两个相邻的气球种类相同被视为不合法的。
kotori想知道,摆成一排m个一共有多少种不同的方案?
由于该数可能过大,只需要输出其对109取模的结果。
解题思路
开始犹豫半天没写,以为用什么Polya定理。然后又想着是不是要dp,拿纸一推算,结果不就是n*(n-1)^(m-1)嘛。
交上去就一直WA。。。
WA了半天,定睛一看,对109取模。。。当做1e9了,太天真了。。。
AC代码
#include<iostream>
using namespace std;
typedef long long ll;
const ll mod = ;
ll pow(ll a, ll n) {
ll res = ;
while(n) {
if(n&) res = res * a % mod;
a = a * a % mod;
n >>= ;
}
return res;
} int main() { ll n, m;
cin>>n>>m;
printf("%lld\n", n*pow(n-, m-) % mod);
return ;
}
C - kotori和出道
链接:https://ac.nowcoder.com/acm/contest/940/C
题目描述
kotori和一些偶像们围成一圈,一共有n个偶像(包括kotori自己),她们的序号顺时针从1到n。现在她们从1号开始进行顺时针报数:1,2,1,2,1……
每个报到2的人出列。直到剩下最后一个人为止。那么这个剩下的人就能被选中发专辑出道啦!
kotori可以暗箱操作决定自己的序号。她很想发专辑,于是向聪明的你求助,初始序号设定为多少才可以呢?
解题思路
约瑟夫环的翻版问题,也就是m==2的特例。
研究了半天约瑟夫环的最后一个人编号,在这篇博客指导下,学会了递推公式
f[1] = 0; i=1
f[i] = (f[i-1] + m) % i; (i>1)
然而还是要O(n)解决这道题。
最后打表找规律,发现每个2^k区间内,答案+2递增,于是O(1)解决。
AC代码
#include<iostream>
using namespace std; typedef long long ll; ll low(ll n) {
ll res = ;
while(res<=n/) res *= ;
return res;
} int main() {
int t; cin>>t;
while(t--) {
ll n;
scanf("%lld", &n);
printf("%lld\n", (n-low(n))*+);
} return ;
}
D - kotori和迷宫
链接:https://ac.nowcoder.com/acm/contest/940/D
题目描述
kotori在一个n*m迷宫里,迷宫的最外层被岩浆淹没,无法涉足,迷宫内有k个出口。kotori只能上下左右四个方向移动。她想知道有多少出口是她能到达的,最近的出口离她有多远?
解题思路
最最基础的迷宫问题,简单BFS,一发AC。
AC代码
#include<iostream>
#include<queue>
using namespace std; char mp[][];
int n, m;
int dis, sx, sy, ans;
struct node {
int x, y, dis;
node(int xx, int yy, int d): x(xx), y(yy), dis(d){}
};
const int dx[] = {, , , -};
const int dy[] = {, -, , };
bool vis[][];
void bfs() {
node n0 = node(sx, sy, );
queue<node> q;
q.push(n0);
vis[sx][sy] = ;
while(q.size()) {
node nd = q.front();
q.pop(); // printf("(%d,%d):%d\n", nd.x, nd.y, nd.dis);
if(mp[nd.x][nd.y]=='e') {
ans++;
if(nd.dis<dis)
dis = nd.dis; continue;
}
for(int i=;i<;i++) {
int nx = nd.x+ dx[i];
int ny = nd.y+ dy[i]; if(nx>= && nx<n && ny>= && ny<m && mp[nx][ny]!='*' && !vis[nx][ny]) {
q.push(node(nx, ny, nd.dis+));
vis[nx][ny] = ;
}
}
}
} int main() {
cin>>n>>m;
for(int i=;i<n;i++) {
scanf("%s", mp[i]);
for(int j=;j<m;j++) {
if(mp[i][j]=='k') {
sx = i, sy = j;
} }
} dis = ;
bfs();
if(dis==) printf("-1\n");
else
printf("%d %d\n", ans, dis);
return ;
}
E - kotori和素因子
链接:https://ac.nowcoder.com/acm/contest/940/E
题目描述
kotori拿到了一些正整数。她决定从每个正整数取出一个素因子。但是,kotori有强迫症,她不允许两个不同的正整数取出相同的素因子。
她想知道,最终所有取出的数的和的最小值是多少?
注:若a%k==0,则称k是a的因子。若一个数有且仅有两个因子,则称其是素数。显然1只有一个因子,不是素数。
解题思路
最后才A这道题,也是一发过。先预处理素因子,简单的DFS。
AC代码
#include<iostream>
#include<cstdio>
#include<set>
using namespace std;
const int maxn = ;
set<int> prms[maxn+];
int n, a[];
void init() {
for(int i=;i<=maxn;i++) {
int j = i, p = ;
while(j>) {
if(j%p==) {
prms[i].insert(p);
j /= p;
}
else {
p++;
}
}
}
}
int ans;
bool vis[maxn];
void dfs(int k, int sum) {
if(k==n) {
ans = min(sum, ans);
return;
}
for(set<int>::iterator it=prms[a[k]].begin();it!=prms[a[k]].end();it++) {
if(!vis[*it]) {
vis[*it] = true;
dfs(k+, sum+*it);
vis[*it] = false;
}
}
} int main() {
init();
cin>>n;
for(int i=;i<n;i++) {
cin>>a[i];
} ans = ;
dfs(, ); if(ans==) {
printf("-1\n");
}
else {
printf("%d\n", ans);
} return ;
}
F - kotori和n皇后
链接:https://ac.nowcoder.com/acm/contest/940/F
题目描述
kotori最近在研究n皇后的问题。
所谓n皇后问题是这样的:一个n*n的地图,上面一共放n个皇后,保证任意两个皇后都不能互相攻击(每个皇后可以攻击同一行、同一列以及同一45度角斜线和135度角斜线上的所有其他皇后)。
kotori思考了很久都无法得出答案,整个人都变成琴梨了。她于是拿了一堆皇后在一个无穷大的棋盘上模拟,按照次序一共放了k个皇后。
但是,皇后的站位太复杂了,kotori甚至不知道是否存在两个皇后会互相攻击。于是她想问问聪明的你,在第i个皇后放置在棋盘上之后,是否存在两个皇后可以互相攻击?
解题思路
如果对原来的n皇后问题的相互攻击处理方法有一定了解的话,这题就非常的easy了。
简单来说,用四个数组分别记录行、列、左斜线、右斜线上是否已经放上了皇后,只需要O(1)就能判断新加入的皇后与前面所有的皇后能飞互相攻击。
利用set存储,时间复杂度O(nlogn)。
AC代码
#include<iostream>
#include<set>
using namespace std;
typedef long long ll;
const ll N = 1e9+;
set<ll> R;
set<ll> C;
set<ll> A;
set<ll> B;
int main() {
int k, xi, yi;
cin>>k;
scanf("%d %d", &xi, &yi);
R.insert(xi);
C.insert(yi);
A.insert(xi+yi);
B.insert(N+xi-yi);
int flag = k+;
for(int i=;i<=k;i++) {
scanf("%d %d", &xi, &yi);
if(flag<k) continue; if(R.find(xi)!=R.end()) flag = i;
else
R.insert(xi); if(C.find(yi)!=C.end()) flag = i;
else
C.insert(yi); if(A.find(xi+yi)!=A.end()) flag = i;
else
A.insert(xi+yi); if(B.find(N+xi-yi)!=B.end()) flag = i;
else
B.insert(N+xi-yi); // printf("%d\n", flag);
} int t; cin>>t;
while(t--) {
int p;
scanf("%d", &p);
if(p>=flag) printf("Yes\n");
else
printf("No\n");
}
return ;
}
G - kotori和抽卡(二)
链接:https://ac.nowcoder.com/acm/contest/940/G
题目描述
kotori最近喜欢上了lovelive这个游戏,因为她发现自己居然也是里面的一个人物。
lovelive有个抽卡系统。共有R、SR、SSR、UR四个稀有度,每次单抽对应稀有度的概率分别是80%,15%,4%,1%。
然而,kotori抽了很多次卡还没出一张UR,反而出了一大堆R,气得她想删游戏了。她想知道n次单抽正好出m张R卡的概率是多少?
解题思路
概率为C(n, m)*p^m*(1-p)^(n-m)。
不会的话翻看《概率论与数理统计》教材吧。不过这好像是高中知识?
AC代码
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll; double C(int n, int m) {
double res = ;
for(int i=;i<=m;i++) {
res = res*(n-i+)/i;
}
return res;
}
double pow(double a, int n) {
double res = ;
while(n) {
if(n&) res *= a;
a *= a;
n >>= ;
}
return res;
}
int main() {
int n, m;
cin>>n>>m;
printf("%.4lf\n", C(n, m)*pow(0.8, m)*pow(0.2, n-m)); return ;
}
H - andy和购物
链接:https://ac.nowcoder.com/acm/contest/940/H
题目描述
解题思路
基于贪心的思想,最贵的货物使用最多的折扣(bj较小的),这样优惠肯定最多,花费也就最少了。
那么将货物价格与折扣分别排序,两者相乘求和即为答案。
时间复杂度O(nlogn+n)。
AC代码
#include<iostream>
#include<algorithm>
using namespace std;
int prc[];
double dsc[];
int main() {
int t; cin>>t;
while(t--) {
int n; cin>>n;
for(int i=;i<n;i++) {
scanf("%d", &prc[i]);
}
for(int i=;i<n;i++) {
scanf("%lf", &dsc[i]);
}
sort(prc, prc+n);
sort(dsc, dsc+n); double res = ;
for(int i=;i<n;i++) {
res += prc[i]*dsc[n--i];
}
printf("%.3lf\n", res);
}
return ;
}
I - andy种树
链接:https://ac.nowcoder.com/acm/contest/940/I
题目描述
andy在他的庄园里种了n棵树,排列成一排,标号为1到n。最开始的时候n棵树的高度都是0,也就是种子刚刚被埋下,树还没有长出来。
andy会一种魔法,他每使用一次魔法,就可以让树标号落在连续区间[l, r]里的树的高度增加1。他可以使用q次这种魔法,然后他很好奇,在使用了q次魔法之后,他的所有树的高度分别是多少呢?
解题思路
树状数组/线段树裸题,分析可以参考我的前一篇博客:树状数组 | 三道模板题小结。
AC代码
#include<iostream>
#include<cstdio>
using namespace std;
#define lowbit(x) ((x)&(-x)) int n, m;
int C[]; // 维护差分信息
int sum(int x) {
int res = ;
while(x) {
res += C[x];
x -= lowbit(x);
}
return res;
}
void add(int x, int d) {
while(x<=n) {
C[x] += d;
x += lowbit(x);
}
}
int main() {
cin>>n>>m;
while(m--) {
int x, y;
scanf("%d %d", &x, &y);
add(x, );
add(y+, -);
} printf("%d", sum());
for(int i=;i<=n;i++) {
printf(" %d", sum(i));
}
return ;
}
J - andy的树被砍了
链接:https://ac.nowcoder.com/acm/contest/940/J
题目描述
andy又开始种树了,他觉得老用魔法不太好,这次他决定老老实实地每天种一棵树,第i天种一颗高度为hi的树,按理说老老实实种树就完事了,哪有那么多问题呢?但是他们学校有个叫kotori的人,非常爱砍树,每天都会把所有andy已经种下的树砍掉ci,如果第i天的时候某棵树的高度已经小于等于ci了,那么这棵树就会死亡,以后再也不会被砍了。并且如果到了第n天,有一些树还没被砍,那么kotori就会在第n + 1天把这些树全部砍死。
解题思路
题意很好理解,对于第i天的树,只要被砍到高度h<=0就被砍死。
如果对每棵树都进行判断,最坏情况下要判断n*n次,显然会超时。
我们可以把砍掉的高度累加求和,即找到最小的d使
h[i] - (c[i]+...+c[d]) <= 0
即
h[i]-(cc[d]-cc[i-1]) ==> h[i]+cc[i-1]<=cc[d]
那么二分查找cc[d],复杂度O(n*logn)。
AC代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std; typedef long long ll;
int h[], c[];
ll cc[];
int main() {
int n; cin>>n;
for(int i=;i<=n;i++) {
scanf("%d", &h[i]);
}
for(int i=;i<=n;i++) {
scanf("%d", &c[i]);
cc[i] = cc[i-] + c[i];
} // 找到最小的d使h[i]-(c[i]+...+c[d])<=0
// 即h[i]-(cc[d]-cc[i-1])==>h[i]+cc[i-1]<=cc[d]
// 二分查找cc[d]
for(int i=;i<=n;i++) {
printf("%d ", lower_bound(cc+, cc++n, h[i]+cc[i-])-cc);
}
putchar('\n');
return ;
}
(完)
北京信息科技大学校赛 题解 | AK记录贴的更多相关文章
- 2018年北京信息科技大学第十届程序设计竞赛暨ACM选拔赛题解
链接:https://www.nowcoder.com/acm/contest/118/A 来源:牛客网 PUBG 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语 ...
- 北京信息科技大学第十一届程序设计竞赛(重现赛)I
I andy种树 题目链接:https://ac.nowcoder.com/acm/contest/940/I 题目描述 andy在他的庄园里种了n棵树,排列成一排,标号为1到n.最开始的时候n棵树的 ...
- “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛题解&&源码【A,水,B,水,C,水,D,快速幂,E,优先队列,F,暴力,G,贪心+排序,H,STL乱搞,I,尼姆博弈,J,差分dp,K,二分+排序,L,矩阵快速幂,M,线段树区间更新+Lazy思想,N,超级快速幂+扩展欧里几德,O,BFS】
黑白图像直方图 发布时间: 2017年7月9日 18:30 最后更新: 2017年7月10日 21:08 时间限制: 1000ms 内存限制: 128M 描述 在一个矩形的灰度图像上,每个 ...
- 2017年浙江理工大学程序设计竞赛校赛 题解&源码(A.水, D. 简单贪心 ,E.数论,I 暴力)
Problem A: 回文 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 1719 Solved: 528 Description 小王想知道一个字 ...
- (java保留n位小数)precise math function 北京信息科技大学第十届ACM程序设计竞赛 第2题
precise math function Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Othe ...
- ZJUT11 多校赛补题记录
牛客第一场 (通过)Integration (https://ac.nowcoder.com/acm/contest/881/B) (未补)Euclidean Distance (https://ac ...
- 北京信息科技大学第十一届程序设计竞赛E-- kotori和素因子(深搜)
链接:https://ac.nowcoder.com/acm/contest/940/E 题目描述 kotori拿到了一些正整数.她决定从每个正整数取出一个素因子.但是,kotori有强迫症,她不允许 ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- SCNU省选校赛第二场B题题解
今晚的校赛又告一段落啦,终于"开斋"了! AC了两题,还算是满意的,英语还是硬伤. 来看题目吧! B. Array time limit per test 2 seconds me ...
随机推荐
- css布局-瀑布流的实现
一.基本思路 1.先看最终的效果图: 2.实现原理:通过position:absolute(绝对定位)来定位每一个元素的位置,并且将当前列的高度记录下来方便下一个dom位置的计算 二.代码实现 1.版 ...
- sql 递归查询,刁刁的
with cte as( select IDPlus,SuperiorsIDPlus,RoleGrade,viplevel,NAME,WeixinId from Member where IDPlus ...
- jquery中on绑定click事件在苹果手机中不起作用
写一个div当做了一个按钮来使用. <div class="button"> <div class="sure"> 确定 </di ...
- windows下怎么给ubantu虚拟机全屏的处理
ubantu版本时16.04 windows下窗口太小需要设置 相信很多人在装虚拟机的时候,遇到了窗口过小不能自适应的问题.我也是查了好多资料,都说安装Vmware Tools即可解决,还有说修改分辨 ...
- Shell 学习(二)
目录 Shell 学习(二) 1 设置环境变量 1.1 基本语法 1.2 实践 2 位置参数变量 2.1 介绍 2.2 基本语法 2.3 位置参数变量应用实例 3 预定义变量 3.1 基本介绍 3.2 ...
- 笔记:Python防止SQL注入
非安全的方式,使用动态拼接SQL 输入' or 1 = 1 or '1 sql ="""SELECT * FROM goods WHERE name = '%s';&qu ...
- 文件的操作repeat
#_author:来童星#date:2019/12/15import os#1# print(os.name)# nt------>windows操作系统#2 用于获取当前操作系统的换行符# p ...
- Windows taskkill
TASKKILL [/S system [/U username [/P [password]]]] { [/FI filter] [/PID processid | /IM imag ...
- 异或+桶——cf768C
有个结论是到最后肯定出现循环节..感觉这种做法有点歪 正解当然是题解啦 虽然到了1e8,但是cf上还是能过的 #include<bits/stdc++.h> #define rep(i,s ...
- manacher/马拉车常用用法一览
因为manacher算法把原来的字符串扩大了两倍,因此在应用时许多二级结论都非常不直观,现场推出来很麻烦,因此笔者在此做个简单整理,如果发现有错误或者有常用的我没有涉及到的,恳请在下方评论区指出,我会 ...