题意:有编号为0~n-1的n个游戏,每个活动都有一个价值(可为负),给你m,s和k,你可以从任意一个编号开始玩,但是下一个游戏必须是编号为(i + k)%n的游戏,你最多能玩m次游戏,问你如果最后你手里要有s的价值,那么你至少一开始要有多少价值。

思路:由裴蜀定理可以知道,如果有n个值首尾相连,间隔为k地走,那么最后会有一个循环节,这样的循环节一共有gcd(n, k)个,每个循环节长度n / gcd(n, k)个。所以我们只要找出所有循环节,并且把每个循环节的最大价值算出来就行了。对于每个循环节,他能获得的最大价值有两种情况,记循环节长度len:

1.m整除len:找长度不超过len的能获得的最大价值,如果走一遍循环节获得价值为正 ,那么再加上sum*(m / len - 1);为负肯定不走好几圈,越走越小的

2.m不整除len:找长度不超过m%len的最大价值,如果走一遍循环节获得价值为正 ,那么再加上sum*(m / len);这里有一种情况可能前面提到的状况不是最优,当走一遍循环节为负并且m>len时,问题其实转化为了上面第一种情况

故当次循环节的最大价值为以上两种情况最大值。

关于求“不超过len的最大价值”和“不超过m%len的最大价值”可以用单调队列解决:开两倍循环节长度的数组储存两个循环节,然后变成前缀和,这样我们可以用单调队列维护,用前缀和相减计算出最大价值。

参考:HDU 6444 Neko's loop(思维+长度不超过L的最大子段和)

代码:

#include<map>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = + ;
const int seed = ;
const int MOD = + ;
const int INF = 0x3f3f3f3f;
ll a[maxn];
ll arr[maxn], q[maxn];
int vis[maxn];
int gcd(int a, int b){
return b == ? a : gcd(b,a % b);
}
ll sum[maxn]; //前缀和
ll cal(int sz, int len){
ll ret = ;
ll head = , tail = ;
for(int i = ; i <= len << ; i++){
if(i == ) sum[i] = arr[i];
else sum[i] = sum[i - ] + arr[i];
if(i <= sz) ret = max(ret, sum[i]);
while(head < tail && q[head] + sz < i) head++;
if(head < tail) ret = max(ret, sum[i] - sum[q[head]]);
while(head < tail && sum[q[tail - ]] >= sum[i]) tail--;
q[tail++] = i;
}
return ret;
}
ll solve(int m, int len){
ll all = ;
for(int i = ; i <= len; i++)
all += arr[i]; //总和
ll ans1 = cal(m % len, len);
ll ans2 = cal(len, len);
if(all > && m / len >= )
ans1 += all * 1LL * (m / len);
if(all > && m / len >= )
ans2 += all * 1LL * (m / len - );
return max(ans1, ans2);
}
int main(){
int T, Case = ;
ll n, m, k, s;
scanf("%d", &T);
while(T--){
scanf("%lld%lld%lld%lld", &n, &s, &m, &k);
for(int i = ; i < n; i++){
scanf("%lld", &a[i]);
vis[i] = ;
}
int num = gcd(n, k); //循环节个数
int len= n / num; //循环节长度
ll Max = -INF;
for(int i = , tt = ; tt <= num && i < n; i++){
if(vis[i]) continue;
vis[i] = ;
int point = i;
for(int j = ; j <= len; j++){
arr[j] = arr[j + len] = a[point];
point = (point + k) % n;
vis[point] = ;
}
Max = max(Max, solve(m, len));
tt++;
}
if(Max >= s)
printf("Case #%d: 0\n", Case++);
else
printf("Case #%d: %lld\n", Case++, s - Max);
}
return ;
}

hdu 6444 网络赛 Neko's loop(单调队列 + 裴蜀定理)题解的更多相关文章

  1. hdu 6444 Neko's loop 单调队列优化DP

    Neko's loop Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  2. HDU 4122 Alice's mooncake shop (单调队列/线段树)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4122 题意:好难读懂,读懂了也好难描述,亲们就自己凑合看看题意把 题解:开始计算每个日期到2000/1/ ...

  3. HDU 4123 Bob’s Race 树形dp+单调队列

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4123 Time Limit: 5000/2000 MS (Java/Others) Memory L ...

  4. HDU 4374 One hundred layer DP的单调队列优化

    One hundred layer Problem Description   Now there is a game called the new man down 100th floor. The ...

  5. HDU 3415 Max Sum of Max-K-sub-sequence(单调队列)

    转载请注明出处:http://blog.csdn.net/u012860063 Max Sum of Max-K-sub-sequence Time Limit: 2000/1000 MS (Java ...

  6. HDU 6319 Problem A. Ascending Rating(单调队列)

    要求一个区间内的最大值和每次数过去最大值更新的次数,然后求每次的这个值异或 i 的总和. 这个序列一共有n个数,前k个直接给出来,从k+1到n个数用公式计算出来. 因为要最大值,所以就要用到单调队列, ...

  7. hdu 3415"Max Sum of Max-K-sub-sequence"(单调队列)

    传送门 题意: 给出一个有 N 个数字([-1000 , 1000],N ≤ 105)的环状序列: 让你求一个和最大的连续子序列,并记录起始点. 要求这个连续子序列的长度小于等于K,加和相同的不同区间 ...

  8. HDU 3415 Max Sum of Max-K-sub-sequence【单调队列】

    <题目链接> 题目大意: 给你一段从1~N的圆形序列,要你求出这段圆形序列中长度不超过K的最大连续子序列之和是多少,并且输出这子序列的起点和终点. 解题分析: 既然是求连续子序列之和,我们 ...

  9. HDU 5089 Assignment(rmq+二分 或 单调队列)

    Assignment Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total ...

随机推荐

  1. 学习计划 mysql 引擎

    -- 什么是引擎? 按照我现在的勒戒,就可以提供 Mysql 对不同表的处理方式,各有优缺点. 就像名字一样,把我们数据库看成法拉利的话,引擎也就是发送机,有的跑的快,有的距离长....... -- ...

  2. flask_SQLAlchemy常用数据类型及列选项

    SQLAlchemy常用数据类型:1. Integer:整形,映射到数据库中是int类型.2. Float:浮点类型,映射到数据库中是float类型.他占据的32位.3. Double:双精度浮点类型 ...

  3. 很多人以为 connect 和 disconnect 应该像 new 和 delete 一样成对出现 这是错误的(只要 sender 或 receiver 其中之一不存在了,connect 会自动失效。QObject::connect 函数是线程安全的)

    其实我写文章也是边查资料边编辑的 有时候是怕自己的阐述不严谨,有时候是怕自己重复造轮子 就像有些人不停的教大家QLabel QDialog QWidget 个人是不屑的 命令模式 用 Qt's Und ...

  4. IIS/ASP.NET访问共享文件夹的可用方式

    [截止2014-10-14] 网上搜索了很多篇文章,所提及的总共有两种方式: 1.Asp.Net模拟登陆: 例如: 实战ASP.NET访问共享文件夹(含详细操作步骤) 实现一个2008serve的II ...

  5. 深度学习之TensorFlow(一)——基本使用

    一.目前主流的深度学习框架Caffe, TensorFlow, MXNet, Torch, Theano比较 库名称 开发语言 速度 灵活性 文档 适合模型 平台 上手难易 Caffe c++/cud ...

  6. spring boot集成shrio用于权限控制

    下面是一个简单的springBoot集成shrio的项目,技术是:spring boot+idea+gradle+shrio+mybatis 1:首先在build.gradle中导入依赖 builds ...

  7. Android APP安装后不在桌面显示图标的应用场景举例和实现方法

    最近在为公司做一款车联网的产品,由于公司本身擅长于汽车解码器的研发,所以该产品的诊断功能的实现除了使用目前市面上车联网产品中大量使用的OBD协议外,还会使用一些专车专用协议去实现一些特殊的诊断功能,如 ...

  8. 评价指标的局限性、ROC曲线、余弦距离、A/B测试、模型评估的方法、超参数调优、过拟合与欠拟合

    1.评价指标的局限性 问题1 准确性的局限性 准确率是分类问题中最简单也是最直观的评价指标,但存在明显的缺陷.比如,当负样本占99%时,分类器把所有样本都预测为负样本也可以获得99%的准确率.所以,当 ...

  9. unp第七章补充之TCP半开连接与半闭连接

    半打开(Half-Open)连接和半关闭(Half-Close)连接.TCP是一个全双工(Full-Duplex)协议,因此这里的半连接"半"字就是相对于全双工的"全&q ...

  10. UVM中的regmodel建模(二)

    UVM的寄存器模型,对一个寄存器bit中有两种数值,mirror值,尽可能的反映DUT中寄存器的值.expected值,尽可能的反映用户期望的值. 几种常用的操作: read/write:可以前门访问 ...