菜鸡永远都在做着变聚的梦。

题意

  有 \(4\) 个点连成一个环,连接顺序依次为 \(1-2-3-4-1\)。相邻两个点之间有个距离 \(d_{i,i+1}\)(特别地,当 \(i=4\) 时为 \(d_{4,1}\))。

  有一个人在 \(2\) 号点,他要完成距离为 \(K\) 的跑步任务并回到 \(2\) 号点,问至少需要跑多长距离。

  \(1\le d_i\le 30000,\space 1\le K\le 10^{18}\)

题解

  剩余系裸题?墨墨的等式练习题?

  考场上瞎写了一波就交了,考后发现转移情况想 sb 了炸成 \(70\) 分了……(啪)

  

  首先你需要会解决这么一个经典问题:给你 \(n(n\le 20)\) 个数 \(a_1,a_2,...,a_n\),求用这些数能加出来的 \(\ge K(K\le 10^{18})\) 的最小值(每个数可以用任意多次),即求 \(a_1 x_1 + a_2 x_2 + ... + a_n x_n\) 在 \([K,\infty)\) 范围内的最小值。

  这就要用到一个东西:剩余系(我也忘了到底叫啥了,也可能是同余系)

  虽然 \(K\) 的范围很大,但注意到 \(a_i\) 的范围并不大,所以我们任取一个数 \(a_p\)(这里为了方便设 \(p\) 为 \(n\)),以此为模数建系。

  或者说,将 \([0,\infty]\) 内的正整数按照模 \(a_p\) 的值分类,所有模 \(a_n\) 的值相同的分入一类。显然我们只需要求出同一类数中最小的能加出来的数(设其为 \(Min\)),因为在这一类中,大于等于 \(Min\) 的所有数显然都能加出来(把 \(Min\) 加上若干个 \(a_n\) 即可),所以并不用考虑它们能不能被其它 \(a_i\) 加出来。

  那怎么求每一类中最小的能加出来的数呢?

  把 \([0,a_p-1]\) 中的每个正整数视为一个点,每个点有 \(n-1\) 条出边,\(i\) 号点的第 \(j\) 条出边指向 \((i+a_j)\% a_n\) 号点,边权为 \(a_j\),然后从 \(0\) 号点出发跑单源最短路即可。

  首先时间复杂度肯定是对的,点数为 \(a_n\),边数为 \(a_n\times (n-1)\),跑 \(\text{dij}\) 复杂度稳定 \(O(a_n\log a_n)\)。

  然后考虑正确性。因为边权是 \(a_i\),所以到 \(x\) 号点的最短路就是 模 \(K\) 得 \(x\) 的一类中 最小的一个能被一堆 \(a_i\) 加出来的数。这种做法用最短路算法保证了时间复杂度的正确性……好神仙啊……

  

  然后考虑本题。我们只需要随便选取一个大小合适的数 作为剩余系的模数就行了。

  不难发现 \(w=d_{1,2}\) 就很合适,\(2w\) 代表从 \(2\) 号点跑到 \(1\) 号点再跑回来。

  可以直接以 \(d_{1,2}\) 为模数建剩余系,那么设 \(dis_{i,j}\) 表示从起点出发到达 \(i\) 号点,距离模 \(2w\) 为 \(j\) 时的最短路。

  \(8w\) 个状态跑 \(\text{dij}\),复杂度 \(O(w\log w)\)。

  我 tm 忘了剩余系的模数可以取最小值,之前一直在取最大值

#include<bits/stdc++.h>
#define ll long long
#define N 100010
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
const ll ll_inf = 9223372036854775807ll >> 1;
using namespace std;
inline ll read(){
ll x=0; bool f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
if(f) return x; return 0-x;
}
ll k;
int w,d[5];
ll dis[5][N];
bool vis[5][N];
priority_queue<pair<ll,pii>, vector<pair<ll,pii> >, greater<pair<ll,pii> > > Q;
void Dij(){
for(int i=0; i<4; ++i)
for(int j=0; j<w; ++j)
dis[i][j]=ll_inf, vis[i][j]=0;
dis[1][0]=0;
Q.push(mp(0,mp(1,0)));
pii tmp; int x,y;
while(!Q.empty()){
//int faq=Q.top().fi;
tmp=Q.top().se; Q.pop();
x=tmp.fi, y=tmp.se;
if(vis[x][y]) continue;
//cout<<faq<<' '<<x<<' '<<y<<endl;
vis[x][y]=1;
int x1=(x+1)%4, x2=(x+3)%4;
int y1=(y+d[x])%w, y2=(y+d[x2])%w;
if(dis[x1][y1]>dis[x][y]+d[x]){
dis[x1][y1]=dis[x][y]+d[x];
Q.push(mp(dis[x1][y1],mp(x1,y1)));
}
if(dis[x2][y2]>dis[x][y]+d[x2]){
dis[x2][y2]=dis[x][y]+d[x2];
Q.push(mp(dis[x2][y2],mp(x2,y2)));
}
}
}
int main(){
int T=read();
while(T--){
k=read();
for(int i=0; i<4; ++i) d[i]=read();
w=min(d[0]<<1,d[1]<<1);
Dij();
//cout<<dis[1][2165%1200]<<endl;
while(dis[1][k%w]>k) ++k;
printf("%lld\n",k);
}
return 0;
}

  scb 神仙推出了个不同的做法(但还是以剩余系为基础),需要对 \(4\) 个式子各求一遍经典问题,但是跑得很快 Orz 大家有兴趣可以去学(mo)一下

【hdu 6071】Lazy Running的更多相关文章

  1. 【数位dp】【HDU 3555】【HDU 2089】数位DP入门题

    [HDU  3555]原题直通车: 代码: // 31MS 900K 909 B G++ #include<iostream> #include<cstdio> #includ ...

  2. 【HDU 5647】DZY Loves Connecting(树DP)

    pid=5647">[HDU 5647]DZY Loves Connecting(树DP) DZY Loves Connecting Time Limit: 4000/2000 MS ...

  3. -【线性基】【BZOJ 2460】【BZOJ 2115】【HDU 3949】

    [把三道我做过的线性基题目放在一起总结一下,代码都挺简单,主要就是贪心思想和异或的高斯消元] [然后把网上的讲解归纳一下] 1.线性基: 若干数的线性基是一组数a1,a2,a3...an,其中ax的最 ...

  4. 【HDU 2196】 Computer(树的直径)

    [HDU 2196] Computer(树的直径) 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 这题可以用树形DP解决,自然也可以用最直观的方法解 ...

  5. 【HDU 2196】 Computer (树形DP)

    [HDU 2196] Computer 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 刘汝佳<算法竞赛入门经典>P282页留下了这个问题 ...

  6. 【HDU 5145】 NPY and girls(组合+莫队)

    pid=5145">[HDU 5145] NPY and girls(组合+莫队) NPY and girls Time Limit: 8000/4000 MS (Java/Other ...

  7. 【hdu 1043】Eight

    [题目链接]:http://acm.hdu.edu.cn/showproblem.php?pid=1043 [题意] 会给你很多组数据; 让你输出这组数据到目标状态的具体步骤; [题解] 从12345 ...

  8. 【HDU 3068】 最长回文

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3068 [算法] Manacher算法求最长回文子串 [代码] #include<bits/s ...

  9. 【HDU 4699】 Editor

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4699 [算法] 维护两个栈,一个栈放光标之前的数,另外一个放光标之后的数 在维护栈的同时求最大前缀 ...

随机推荐

  1. Jconsole、JvisualVM无法连接Tomcat服务

    转载自:https://blog.csdn.net/qq_27790011/article/details/88799587 打开TomcatXw.exe找到java选项卡,添加以下参数 -Dcom. ...

  2. Pythoncookbook(数据结构与算法)在字典中将键映射到多个值上的方法

    Python cookbook(数据结构与算法)在字典中将键映射到多个值上的方法 本文实例讲述了Python在字典中将键映射到多个值上的方法.分享给大家供大家参考,具体如下: 问题:一个能将键(key ...

  3. for循环使用

    cat > a.sh <<EOF #!/bin/bash export NODE_NAMES=(kube-test1 kube-test2 kube-test3 kube-test4 ...

  4. OpenStack组件——Neutron网络服务(2)

    1.虚拟机获取 ip 1)用 namspace 隔离 DHCP 服务 Neutron 通过 dnsmasq 提供 DHCP 服务,而 dnsmasq 通过 Linux Network Namespac ...

  5. Object中有哪些方法及其作用

    你知道Object中有哪些方法及其作用吗? 一.引言 二.Object方法详解 1.1.registerNatives() 1.2.getClass() 1.2.1.反射三种方式: 1.3.hashC ...

  6. 旗舰版win7系统中GraphEdit执行Loading a Graph From an External Process失败对策

    操作系统:旗舰版win7 DirectShow SDK: 9.0 IDE环境:VS2008 以下代码参考MSDN: HRESULT AddToRot(IUnknown *pUnkGraph, DWOR ...

  7. [转帖]国科微发布纯正国产SSD主控 龙芯IP内核,速度可达500MB/s

    国科微发布纯正国产SSD主控龙芯IP内核,速度可达500MB/s https://www.expreview.com/68071.html 自主内核 龙芯处理器. 2019.4. 在存储芯片领域,中国 ...

  8. C++多线程基础学习笔记(七)

    一.std::async和std::future的用法 std::async是一个函数模板,std::future是一个类模板 #include <iostream> #include & ...

  9. 走环概率问题(至今有点迷)--牛客第二场( Eddy Walker)

    思路: 概率结论题,好像属于线性递推,现在也不太懂(lll¬ω¬) #define IOS ios_base::sync_with_stdio(0); cin.tie(0); #include < ...

  10. Windows下使用SVN版本控制工具

    一.SVN工作原理 SVN(SubVersion)的基本工作思路是这样的:在一台服务器上建立一个源代码库,库里可以存放许多不同项目的源程序,由源代码库管理员统一管理这些源程序. 每个用户在使用源代码库 ...