LG2662 牛场围栏 和 test20181107 数学题
P2662 牛场围栏
题目背景
小L通过泥萌的帮助,成功解决了二叉树的修改问题,并因此写了一篇论文,
成功报送了叉院(羡慕不?)。勤奋又勤思的他在研究生时期成功转系,考入了北京大学光华管理学院!毕业后,凭着自己积累下的浓厚经济学与计算机学的基础,成功建设了一个现代化奶牛场!
题目描述
奶牛们十分聪明,于是在牛场建围栏时打算和小L斗智斗勇!小L有N种可以建造围栏的木料,长度分别是l1,l2 … lN,每种长度的木料无限。
修建时,他将把所有选中的木料拼接在一起,因此围栏的长度就是他使用的木料长度之和。但是聪明的小L很快发现很多长度都是不能由这些木料长度相加得到的,于是决定在必要的时候把这些木料砍掉一部分以后再使用。
不过由于小L比较节约,他给自己规定:任何一根木料最多只能削短M米。当然,每根木料削去的木料长度不需要都一样。不过由于测量工具太原始,小L只能准确的削去整数米的木料,因此,如果他有两种长度分别是7和11的木料,每根最多只能砍掉1米,那么实际上就有4种可以使用的木料长度,分别是6, 7,10, 11。
因为小L相信自己的奶牛举世无双,于是让他们自己设计围栏。奶牛们不愿意自己和同伴在游戏时受到围栏的限制,于是想刁难一下小L,希望小L的木料无论经过怎样的加工,长度之和都不可能得到他们设计的围栏总长度。不过小L知道,如果围栏的长度太小,小L很快就能发现它是不能修建好的。因此她希望得到你的帮助,找出无法修建的最大围栏长度。
这一定难不倒聪明的你吧!如果你能帮小L解决这个问题,也许他会把最后的资产分给你1/8哦!
输入输出格式
输入格式:
输入的第一行包含两个整数N, M,分别表示木料的种类和每根木料削去的最大值。以下各行每行一个整数li(1< li< 3000),表示第i根木料的原始长度。
输出格式:
输出仅一行,包含一个整数,表示不能修建的最大围栏长度。如果任何长度的围栏都可以修建或者这个最大值不存在,输出-1。
输入输出样例
说明
40 % :1< N< 10, 0< M< 300
100 % :1< N< 100, 0< M< 3000
CaptainSlow的题解
规模较小,直接上可行解DP(有个叫_DYT大佬搞了一波分析证明这个解若存在是小于\(9 \times 10^6\)) 当然我们要考虑更好的解法,如果是初中我也会写可行解DP,当然考场上实在写不出来我还是应该打个暴力骗骗满分的。
PART 1 无解?
问题确实可能无解,分两种情况:
存在数字1
如果有1这个数字,那么所有的数字都可以被表示出来,就不存在不能表示出的数了所有数的gcd大于1
设这些数为\(A_1, A_2,...,A_n\),设\(q=gcd(A_1, A_2,...,A_n)\),则\(q|A_1x_1+A_2x_2+...+A_nx_n\)(\(x_1,x_2,...,x_n \in Z\))。这是一个很显然的结论,学习整除的时候是必回讲到的。所以,由于\(q > 1\),必然存在不能表示出来的数,即\(\forall q \nmid m\),都是不符合条件的数,显然这个\(m\)是可以到无穷大的。
这两者情况我们可以先特判出来,而剩下的就是\(q=1\)的情况了,这样的话是肯定存在最大的不能表示出来的数的。 这个很显然。
PART 2 寻找
我们如何去寻找这个最大的不能被表示出来的数呢? 我们考虑所有可以被表示出来的数构成的数集\(S\),由最小数原理可知,\(S\)中一定存在最小的\(s_0\)。考虑模\(s_0\)的每一个剩余系,记为\(K_i=\lbrace x|x \equiv i\pmod{s_0}\rbrace,i=0,1,2,...,s_0-1\)。 显然\(s_0=min(A_i)\)。对\(\forall K_i\),由最小数原理,存在最小的能被表示出来的\(t_i\),\(t_i=s_0*p+i\),显然\(p>0\),否则与\(s_0\)的最小性矛盾。那么对每一个\(K_i\),最大不能被表示出来的数就是\(s_0*(p-1)+i\)。这样,问题就转化为了求每一个这样的\(t_i\),这时候,我们就引入这个被称为剩余系最短路的算法了。我们可以把每个剩余系\(K_i\)抽象为图中的点,那么连接它们的边就是\(A_i\)中的那些数。然后就用普通的最短路更新方式就可以了。我选择了用Dijkstra算法。
#include <cstdio>
#include <cstring>
#include <algorithm>
const int ARSIZE = 4005;
const int INF = 0x7f7f7f7f;
int N, M, L[ARSIZE], tot_l = 0, Q[ARSIZE];
bool exist[ARSIZE] = {0}, used[ARSIZE] = {0};
inline int gcd(int a, int b) {
for (a < b ? std::swap(a, b) : (void)0; b; std::swap(a, b)) a %= b;
return a;
}
int dijkstra();
int main() {
scanf("%d%d", &N, &M);
int j, li, gd = 0;
for (int i = 0; i < N; i++) {
scanf("%d", &li);
gd = gcd(gd, li);
for (j = 0; j <= M && j < li; j++) exist[li - j] = true, gd = gcd(li - j, gd); // 很多人WA,半天查不出错,很可能就是只算了所有L[i]的gcd
}
if (exist[1] || gd > 1) puts("-1");
else printf("%d\n", dijkstra());
return 0;
}
int dijkstra() {
memset(Q, 0x7f, sizeof(Q));
int i, v, k;
for (Q[0] = 0, i = 2; i <= 3000; i++) // 初始化
if (exist[i]) L[tot_l++] = i;
int MOD = L[0];
while (true) {
for (i = 0, k = -1; i < MOD; i++)
if (!used[i] && (k == -1 || Q[i] < Q[k])) k = i;
if (k == -1) break;
used[k] = true;
for (i = 1; i < tot_l; i++)
if (!used[v = (k + L[i]) % MOD]) Q[v] = std::min(Q[v], Q[k] + L[i]); // 更新其他剩余系
}
int res = -1;
for (i = 1; i < MOD; i++) res = std::max(res, Q[i] - MOD);
return res;
}
数学题(num)
题目描述
老师给小C 布置了一道数学题作为家庭作业:
给定一个数k,写出k 的倍数中各位之和最小为多少?
小C 不会做,希望你能帮帮他。
输入描述
一行一个正整数k。
输出描述
一行一个正整数,表示答案。
输入样例& 输出样例
num1.in
6
num1.out
3
num2.in
41
num2.out
5
样例说明
- 当k = 6 时,6 * 2 = 12,1 + 2 = 3,可以证明最小答案为3。
- 当k = 41 时,41 * 271 = 11111,1 + 1 + 1 + 1 + 1 = 5,可以证明最小答案为5。
数据范围
测试点编号 | k |
---|---|
1-6 | $ \leq 20$ |
7-20 | \(\leq 10^5\) |
刘老爷算法
考虑建立模n意义下的n个点,用追加数字的方式建边,由于是枚举n的倍数,所以到0点的最短路即为答案。
起点为1-9,建边边权,0-9连向摸意义下的多一位的点。
时间复杂度\(O(10 n \log n)\),注意n=1时要特判掉,不然根本就没建图,跑出来答案为INF。
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<algorithm>
#include<string>
template<class T>T read(T&x)
{
T data=0;
int w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
{
data=data*10+ch-'0';
ch=getchar();
}
return x=data*w;
}
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int INF=0x3f3f3f3f;
const int MAXN=1e5+7;
int n;
struct edge
{
int nx,to,w;
}e[MAXN*10];
int head[MAXN],ecnt;
void addedge(int x,int y,int w)
{
e[++ecnt].to=y,e[ecnt].w=w;
e[ecnt].nx=head[x],head[x]=ecnt;
}
priority_queue <pii> H;
bool vis[MAXN];
int dis[MAXN];
int main()
{
freopen("num.in","r",stdin);
freopen("num.out","w",stdout);
read(n);
if(n==1) // edit 1
{
puts("1");
return 0;
}
for(int i=1;i<n;++i)
for(int j=0;j<10;++j)
addedge(i,(i*10+j)%n,j);
fill(dis,dis+n,INF);
for(int i=1;i<=9;++i)
{
dis[i]=i;
H.push(pii(-dis[i],i));
}
while(H.size())
{
int x=H.top().second;
H.pop();
if(vis[x])
continue;
vis[x]=1;
for(int i=head[x];i;i=e[i].nx)
{
int y=e[i].to,w=e[i].w;
if(dis[y]>dis[x]+w)
{
dis[y]=dis[x]+w;
H.push(pii(-dis[y],y));
}
}
}
printf("%d\n",dis[0]);
return 0;
}
标解
LG2662 牛场围栏 和 test20181107 数学题的更多相关文章
- luoguP3951 小凯的疑惑/P2662 牛场围栏
其实就是当年sxy给我讲的墨墨的等式,只是当时比较菜听得似懂非懂. 小凯的疑惑 去年noipday1t1,当时随便猜了个结论结果猜对了,现在瞎证一下,答案是a*b-a-b. 设a为a,b中较小的一个, ...
- 【同余最短路】洛谷 P2662 牛场围栏
关于同余最短路的部分 [同余最短路]P3403跳楼机/P2371墨墨的等式 [P2662牛场围栏] 题目背景 小L通过泥萌的帮助,成功解决了二叉树的修改问题,并因此写了一篇论文, 成功报送了叉院(羡慕 ...
- Luogu2662 牛场围栏(最短路)
小凯的疑惑升级版的升级版.答案若存在不会超过30002-3000,暴力dp似乎勉强可以过.当然这不优美. 注意到如果能拼出长度为l的围栏,就一定能拼出长度为l+kx的围栏,其中x为最短的(或任意一个) ...
- 牛场围栏(vijos 1054)
题目大意: 给出N种木棍(每种木棍数量无限)的长度(<=3000),每根木棍可以把它切掉[1,M]的长度来得到新的木棍. 求最大的不能被组合出来的长度. 如果任何长度都能组合出来或者最大值没有上 ...
- luogu P2662 牛场围栏
传送门 因为一个木板可以切掉最多\(m\),所以可以先预处理哪些长度的木板可用,开个桶,然后对\([l-m,l]\)打标记,再把打了标记的数取出来 假设可用长度\(a_1,a_2,,,a_n\)从小到 ...
- 洛谷 P2662 牛场围栏
做法是这样的: 首先暴力把所有可能的边长搞出来..(当然<=0的不要) 排序边长+去重, 当且仅当可行边长里面有1时,任何长度都能取到,输出-1 当且仅当所有可行边长的gcd大于1时,不能取到的 ...
- vijos 1054 牛场围栏 【想法题】
这题刚看完后第一个想到的方法是背包 但仔细分析数据范围后会发现这题用背包做复杂度很高 比如对于这样的数据 2 100 2999 2898 (如果有神犇可以用背包过掉这样的数据 请回复下背包的做法) - ...
- P1578 奶牛浴场
P1578 奶牛浴场 题目描述 由于John建造了牛场围栏,激起了奶牛的愤怒,奶牛的产奶量急剧减少.为了讨好奶牛,John决定在牛场中建造一个大型浴场.但是John的奶牛有一个奇怪的习惯,每头奶牛都必 ...
- 洛谷1578:[WC2002]奶牛浴场——题解
https://www.luogu.org/problemnew/show/P1578#sub 由于John建造了牛场围栏,激起了奶牛的愤怒,奶牛的产奶量急剧减少.为了讨好奶牛,John决定在牛场中建 ...
随机推荐
- Java的集合类之 List 接口用法
集合其实在本质上面就是数据结构,它封装了一些底层的数据结构等操作进行操作. 集合的长度是可变的,用来存放对象的引用.常见的集合类有List集合.Set集合.Map集合. 1. List接口 List是 ...
- 自己实现简单版SpringMVC
SpringMVC的主要作用是:从http请求中得到一个url字符串和对应的请求参数,根据该字符串找到Controller中的一个方法,利用反射执行该方法,将结果返回给前端 1,初始化 将url请求路 ...
- Spring MVC 问题归纳
记录一些在Spring MVC配置中出现的问题 一.配置tomcat包没有加载 错误: idea调试web项目时出现:java.lang.ClassNotFoundException:org.spri ...
- 19.Python略有小成(面向对象Ⅰ)
Python(面向对象Ⅰ) 一.面向对象初识 回顾面向过程编程与函数式编程 # 面向过程编程 测量对象的元素个个数. s1 = 'fjdsklafsjda' count = 0 for i in s1 ...
- L2R 三:常用工具包介绍之 XGBoost与LightGBM
L2R最常用的包就是XGBoost 和LightGBM,xgboost因为其性能及快速处理能力,在机器学习比赛中成为常用的开源工具包, 2016年微软开源了旗下的lightgbm(插句题外话:微软的人 ...
- 基础数字电路的Verilog写法
Verilog是硬件描述电路,我对此一直稀里糊涂,于是将锆石科技开发板附带的的一些基础数字电路Verilog程序整理记录下来,并且查看他们的RTL视图,总算有点理解了. 1.基本运算符 module ...
- ArcGIS 字段计算器 Python 坑
最近要处理个简单数据,一个字段中为文本类型,包含各种描述.要求是包含平方米的数值提取出来,变成数值,如果包含多个,则把各个值累加起来. 比如 字段值为 “非法占用100平方米” 处理后结果为 100 ...
- Web SSH远程连接利器:gotty
Web SSH远程连接利器:gotty 这个东东能让你使用浏览器连接你远程的机器! 一. 环境准备 下载https://github.com/yudai/gotty. 请先配置好 Golang 环境, ...
- iOS-右滑返回,利用Runtime添加全屏Pop手势
项目中经常会遇到类似需求,需要在某控制器增加全屏右滑返回功能. 在我们不隐藏 NavigationBar 的前提下,系统会自动替我增加此功能,只是它作用的范围仅仅在屏幕左边有限区域. 我们需要在整个界 ...
- 记支付宝接口对接,涉及到提取证书SN号的解决方案
支付宝针对.NET SDK并未封装有提取证书SN序列号的方法,仅针对Java平台才有对应的方法(赤裸裸的歧视啊~~) 要想在提取这个SN序列号有两种方案: 1. 直接用Java SDK包来提取SN 2 ...