2017 ACM/ICPC Asia Regional Shenyang Online(部分题解)
题意
输入n和k,表示输入n个整数和可以擦除的次数k,如果至多擦除k次能是的数组中的序列是不上升或者是不下降序列,就是魔力数组,否则不是。
解题思路
分别求最长不下降和不上升子序列的长度,看不符合要求的数字和k的大小。
这里使用优化后的求解最长不上升和不下降子序列的算法。
#include <cstdio>
#include <algorithm>
using namespace std; const int maxn = ;
const int inf = ;
int A[maxn], B[maxn], g[maxn], d[maxn];
int n, t; int main()
{
int T;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &t);
for(int i = ; i < n; i++) {
scanf("%d", &A[i]);
} for(int i = ; i <= n; i++) {
g[i] = inf;
}
for(int i = ; i < n; i++) {
int k = upper_bound(g + , g + n + , A[i]) - g;
d[i] = k;
g[k] = A[i];
}
int s1 = ;
for(int i = ; i < n; i++)
if(s1 < d[i])
s1 = d[i]; int j = ;
for(int i = n - ; i >= ; i--) {
B[j++] = A[i];
}
for(int i = ; i <= n; i++) {
g[i] = inf;
}
for(int i = ; i < n; i++) {
int k = upper_bound(g + , g + n + , B[i]) - g;
d[i] = k;
g[k] = B[i];
}
int s2 = ;
for(int i = ; i < n; i++)
if(s2 < d[i])
s2 = d[i]; //printf("%d %d\n",s1,s2);
int ans = max(s1, s2);//最长上升或者下降子序列,取大值意味者修改更少
if(n - t <= ans)
printf("A is a magic array.\n");
else
printf("A is not a magic array.\n");
}
return ;
}
题意
给出n个屏幕和k个光源,要求的是从n个屏幕中任意的k个屏幕显示不同颜色的光源至少需要几根电缆
解题思路
有两个出发点
从屏幕出发,前k个屏幕都单独和k个光源连接,剩下n-k个屏幕应该和每个光源都有连接,否则随意挑的时候,可能会出现重复。故总的电缆数是k+(n-k)*k。
从光源出发,每个光源至少应该和(n-k+1)个屏幕相连,这样选出的k个屏幕才能可以组成k种不同的光源点。故总的电缆数是(n-k+1)* k。
#include <cstdio> int main()
{
long long n, k;
while(scanf("%lld%lld", &n, &k) != EOF) {
printf("%lld\n", k *( n - k + ));
}
return ;
}
题意
首先定义了斐波那契数列F0 = 0,F1 = 1;
Fn = Fn - 1 + Fn - 2(n>=2).
给出一个k,如果一个正整数能够由连续(可重复)的斐波那契数加和得到,就是一个好数,否则就是一个坏数。现在给出一个k,问最小的坏数是多少。
解题思路
首先应该想到的应该是当k = 1 时,最小的坏数是5 - 1 = 4;
当k = 2 时,最小的坏数是13 - 1 = 12;
当k = 3 时,最小的坏数是34 - 1 = 33;
然后如果拿5为斐波那契数的第一项,8位第二项,可以发现规律就是对于输入的k,答案是第f(2*k+1)项斐波那契数 - 1。
不过题中给出的k的范围是(1<=k<=10^9),最大可能是第2*10^9项斐波那契数。就需要矩阵快速幂计算某一项斐波那契数了。代码如下:
#include <cstdio>
#include <cstring>
typedef long long ll;
const int mod = ;
struct Matrix {
ll x[][];
};
Matrix Mmul(Matrix a, Matrix b) {
Matrix tmp;
memset(tmp.x, , sizeof(tmp.x));
for(int i = ; i < ; i++) {
for(int j = ; j < ; j++) {
for(int k = ; k < ; k++) {
tmp.x[i][j] = (tmp.x[i][j] + a.x[i][k] * b.x[k][j] % mod) % mod;
}
}
}
return tmp;
}
Matrix Mqpow(Matrix a, ll n) {
Matrix tmp;
for(int i = ; i < ; i++) {
for(int j = ; j < ; j++) {
tmp.x[i][j] = i == j ? : ;
}
} while(n) {
if(n&)
tmp = Mmul(tmp, a);
a = Mmul(a, a);
n >>= ;
}
return tmp;
}
int main()
{
ll k;
while(scanf("%lld", &k) != EOF) {
Matrix st;
st.x[][] = ; st.x[][] = ;
st.x[][] = ; st.x[][] = ; Matrix init;
init.x[][] = ; init.x[][] = ;
init.x[][] = ; init.x[][] = ; st = Mqpow(st, * k + );
st = Mmul(st, init);
/*for(int i = 0; i < 2; i++) {
for(int j = 0; j < 2; j++) {
printf("%lld ", st.x[i][j]);
}
puts("");
}*/
printf("%lld\n", (st.x[][] - + mod) % mod);
}
return ;
}
HDU 6201 transaction transaction transaction
题意
给出由n-1条边联通的n个顶点的图(可以将其方便的看为一棵树),每个顶点都有卖一本书的价格,但是每个地方都不同,一个商人想从中赚取差价,但是点与点之间还有路费,问这个人最多能赚取多少钱?
解题思路
先将其转换为一棵树来处理,定义两种状态分别是:dp[u][0] 表示从u及其子孙结点中的一点买书(包括所花的路费)的最小值(由于是负数,所以也即求最大值)
dp[u][1]表示从u及其子孙结点中的一点卖书(包括所花的路费)的最大值
那么从u结点及其子孙结点买再卖给u及其子孙结点的利润,也就是一个结点的利润是dp[u][0] +dp[u][1]。最后的答案就是取所有结点的最大值即可。代码如下:
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = + ; struct Node {
int v, w;
Node(int _v, int _w):v(_v),w(_w){};
}; vector<Node> vec[maxn];
int val[maxn];
int n, ans;
int dp[maxn][]; void dfs(int u, int pre) {
dp[u][] = -val[u];//从u结点及其子孙结点中的一点买书所花的最少的钱(一定是一个负数)
dp[u][] = val[u]; //从u结点及其子孙结点中的一点卖书所赚的最多的钱
for(int i = ; i < vec[u].size(); i++) {
int v = vec[u][i].v;
int w = vec[u][i].w;
if(v == pre) continue;
dfs(v, u);
//当前结点(买书)和它的子结点(买书)“加上”路费的值 谁更大(都是负数)
dp[u][] = max(dp[u][], dp[v][] - w);
//当前结点(卖书)和它的子结点(卖书)减去路费的值 谁更大
dp[u][] = max(dp[u][], dp[v][] - w);
}
ans = max(ans, dp[u][] + dp[u][]);
} int main()
{
int T;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = ; i <= n; i++) {
scanf("%d", &val[i]);
vec[i].clear();
}
for(int i = ; i <= n - ; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
vec[u].push_back(Node(v, w));
vec[v].push_back(Node(u, w));
}
ans = ;
dfs(, -);
printf("%d\n", ans);
}
return ;
}
题意
给出n摞牌,排成一行,然后n个数表示每摞有多少张牌,还给出每一摞牌的罚值,我们可以通过将第一摞移动到最后来改变次数,使得拿更多的牌,拿取一摞的规则是一张一张的拿到手中并且使他们面朝上,拿完之后翻转一定数目的牌使之朝下,如果能够翻转的牌数等于该摞牌的罚值,表示可以继续往后拿,直至拿完。问最少移动几次使得拿取最多的牌。
解题思路
问循环移动的次数,我们先将其复制一遍到它的后面,然后通过最大子段和的思想,每次选取满足条件的最大子段,不同的是限制的条件是a[i]-b[i]的差要大于等于0,而结果是所有牌的数目,所以需要分开计算。代码如下:
#include <cstdio>
const int inf = ;
const int maxn = + ;
int a[maxn], b[maxn]; int main()
{
int n;
while(scanf("%d", &n) != EOF) {
for(int i = ; i <= n; i++) {
scanf("%d", &a[i]);
a[i + n] = a[i];
}
int x;
for(int i = ; i <= n; i++) {
scanf("%d", &x);
b[i] = a[i] - x;
b[i + n] = b[i];
} int sum1 = , sum2 = ;
int ans = ;
int l = , r = , tmp = ;
for(int i = ; i <= * n; i++) {
sum1 += a[i];
sum2 += b[i];
if(sum1 > ans) {
ans = sum1;
l = tmp;
r = i;
}
if(sum2 < ) {
sum1 = ;
sum2 = ;
tmp = i + ;
if(tmp > n + )
break;
}
}
printf("%d\n", l-);
}
return ;
}
2017 ACM/ICPC Asia Regional Shenyang Online(部分题解)的更多相关文章
- 2017 ACM/ICPC Asia Regional Shenyang Online spfa+最长路
transaction transaction transaction Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 132768/1 ...
- HDU 6205(尺取法)2017 ACM/ICPC Asia Regional Shenyang Online
题目链接 emmmm...思路是群里群巨聊天讲这题是用尺取法.....emmm然后就没难度了,不过时间上3000多,有点.....盗了个低配本的读入挂发现就降到2800左右, 翻了下,发现神犇Clar ...
- HDU 6198(2017 ACM/ICPC Asia Regional Shenyang Online)
思路:找规律发现这个数是斐波那契第2*k+3项-1,数据较大矩阵快速幂搞定. 快速幂入门第一题QAQ #include <stdio.h> #include <stdlib.h& ...
- 2017 ACM/ICPC Asia Regional Shenyang Online array array array
2017-09-15 21:05:41 writer:pprp 给出一个序列问能否去掉k的数之后使得整个序列不是递增也不是递减的 先求出LIS,然后倒序求出最长递减子序列长度,然后判断去k的数后长度是 ...
- 2017 ACM/ICPC Asia Regional Shenyang Online card card card
题意:看后面也应该知道是什么意思了 解法: 我们设置l,r,符合条件就是l=起始点,r=当前点,不符合l=i+1 学习了一下FASTIO #include <iostream> #incl ...
- 2017 ACM/ICPC Asia Regional Shenyang Online transaction transaction transaction
Problem Description Kelukin is a businessman. Every day, he travels around cities to do some busines ...
- 2017 ACM/ICPC Asia Regional Shenyang Online number number number
题意:求n个斐波那契数列组合都无法得到的最小数字 解法: 1 我们先暴力的求出前面几个数字 2 然后再暴力的求递推 3 接着矩阵快速幂(没写错吧?) /*#include<bits/stdc++ ...
- 2017 ACM/ICPC Asia Regional Shenyang Online cable cable cable
Problem Description Connecting the display screen and signal sources which produce different color s ...
- 2017 ACM/ICPC Asia Regional Shenyang Online
cable cable cable Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...
随机推荐
- 排序算法(sorting algorithm) 之 选择排序(selection sort)
https://en.wikipedia.org/wiki/Selection_sort loop1: 4,6,1,3,7 -> 4,6,1,3,7 4,6,1,3,7 -> ,3,7 1 ...
- java面试一、1.3线程与进程
免责声明: 本文内容多来自网络文章,转载为个人收藏,分享知识,如有侵权,请联系博主进行删除. 1.3.进程和线程 线程和进程的概念.并行和并发的概念 线程和进程: 线程:是程序执行流的最小单元 ...
- uva12307(旋转卡壳)
省选前练模板系列 #include<iostream> #include<cmath> #include<cstdio> #include<cstring&g ...
- 2018年2月19日我的java学习(——)
在学完了类和对象的时候,开始对面向对象的思想有了一点认识,不过也不是完全的理解了. 就现在的学习状态来说,是非常的不错的,但是在学习的内容来说,我学的好像只是跟随这 站长的思路而已,也许是经验不足吧. ...
- Android-Java-普通类与抽象类(覆盖)&方法重载
覆盖都是子类与父类之间 & 接口与实现类之间 才会产生:覆盖 有很多名称,覆盖,复写,重写 都是一个意思: 注意:重载都是方法之间 方法同名 不同参数,就属于重载: 普通类-覆盖: 描述An ...
- 《JavaScript 高级程序设计》读书笔记四 变量 作用域 内存
一 变量(基本类型和引用类型) a.基本类型保存值,保存在栈内存,引用类型保存指针,保存在堆内存: b.所有函数的参数都是按值进行传递的,不管参数是何种类型: c.检测类型 typeof ...
- 剑指offer面试题17:合并两个排序的链表
题目:输入两个递增排序的链表,合并这两个链表并使新链表中的节点人是按照递增排序的.解题思路:两个链表分别都已经是有序的了,遍历链表的时候只要比较两个链表当前位置大小,取出最小的添加到新链表中. 可以有 ...
- 安全运维中基线检查的自动化之ansible工具巧用
i春秋作家:yanzm 原文来自:安全运维中基线检查的自动化之ansible工具巧用 前几周斗哥分享了基线检查获取数据的脚本,但是在面对上百台的服务器,每台服务器上都跑一遍脚本那工作量可想而知,而且都 ...
- 【渗透攻防Web篇】SQL注入攻击高级
前言 前面我们学习了如何寻找,确认,利用SQL注入漏洞的技术,本篇文章我将介绍一些更高级的技术,避开过滤,绕开防御.有攻必有防,当然还要来探讨一下SQL注入防御技巧. 目录 第五节 避开过滤方法总结 ...
- 生成uuid唯一标识符
generate_uuid: function(){ var d = new Date().getTime(); if(window.performance && typeof win ...