codeforces 1244C (思维 or 扩展欧几里得)
题意分析
已知 n , p , w, d ,求x , y, z的值 ,他们的关系为:
x + y + z = n
x * w + y * d = p
思维法
当 y < w 的时候,我们最多通过1e5次枚举确定答案
而当 y >= w 的时候,平局所得分为:y * d = (y-w)*d + w*d ,可以看作平局的局数为 y - w ,多出的w*d贡献给 (w*d)/w = d 局胜局,所以胜局为 x + d ,说明此时用x+y局胜局和平局得到的分数可以由 x + d + y - w 局胜局和平局得到,同时此时的胜局+平局次数更少,所以枚举 y > w 的情况是没有意义的,完全可以通过枚举 y = {0 ~ w - 1} 得到答案
综上所述,我们只需要在 [0,w) 范围内枚举y即可得到答案
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip> #define bug cout << "**********" << endl
#define show(x, y) cout<<"["<<x<<","<<y<<"] "
#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + ;
const int Max = 5e3 + ; ll n, sum;
ll win, draw; int main()
{
#ifdef LOCAL
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
scanf("%lld%lld%lld%lld", &n, &sum, &win, &draw);
for(ll y = ; y < win ; y ++)
{
if ((sum - y * draw) % win)
continue;
ll x = (sum - y * draw) / win;
if(x + y <= n && x >= )
{
printf("%lld %lld %lld\n",x,y,n-x-y);
return ;
}
}
printf("-1\n");
return ;
}
扩展欧几里得法
扩展欧几里得算法才是这个题目的正解,从式子:x * w + y * d = p 中,可以看出其正好对应扩展欧几里得公式:x * a + y * b = gcd(a,b) ,借助扩展欧几里得公式,我们可以得到x * w + y * d = p的一组解,具体步骤如下:
1)用扩展欧几里得公式求:
x0 * w + y0 * d = gcd(w,d)
得到了x0,y0
2)将上述式子两边同乘 k = p / gcd(w,d) ,【必须保证 (p % gcd(w,d)) == 0 ,否则无解】,得到:
x0 * k * w + y0 * k * d = gcd(w,d) * k
即
x0 * k * w + y0 * k * d = p
这样, x = x0*k , y = y0*k 就是式子 x * w + y * d = p 的一组解,
3)由于x,y,z需要满足
x + y + z = n
因此,我们通过调整x,y,使得上式得以满足,为此,我们需要让x + y 的值尽量小;注意到 w > d ,说明当 y 取最小值的时候,x + y 取最小值,如果此时 x + y <= n ,说明有解,否则无解
又根据 x * w + y * d = p ,我们得知 y 每次变化:+- w/gcd(w,d) ,所以y 的最小值即为
y = ( y0 * k ) % (w/gcd(w,d))
4)最后,根据得到的y,求出x 和 z 的值,随后,判断 x + y 是否小于 n ,满足即输出 x , y , z,否则说明无解
(注意求 y 的时候进行取模操作,不然会爆 long long )
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip> #define bug cout << "**********" << endl
#define show(x, y) cout<<"["<<x<<","<<y<<"] "
#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int Max = 5e3 + ; ll n, sum;
ll win, draw; ll exgcd(ll a, ll b, ll &x, ll &y)
{
if (b == )
{
x = ;
y = ;
return a;
}
ll r = exgcd(b, a % b, x, y);
ll t = x;
x = y;
y = t - (a / b) * y;
return r;
} int main()
{
#ifdef LOCAL
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
scanf("%lld%lld%lld%lld", &n, &sum, &win, &draw);
ll x, y;
ll gcd = exgcd(win, draw, x, y); if ((sum % gcd) == )
{
ll mod = win / gcd;
y = ((y%mod)*(sum/gcd%mod)%mod + mod)%mod;
x = (sum - y * draw) / win;
if(x >= && y >= && x + y <= n)
{
printf("%lld %lld %lld\n",x,y,n-x-y);
return ;
}
}
printf("-1\n");
return ;
}
codeforces 1244C (思维 or 扩展欧几里得)的更多相关文章
- Codeforces 724C Ray Tracing 扩展欧几里得
吐槽:在比赛的时候,压根就没想到这题还可以对称: 题解:http://blog.csdn.net/danliwoo/article/details/52761839 比较详细: #include< ...
- 【扩展欧几里得】BAPC2014 I Interesting Integers (Codeforces GYM 100526)
题目链接: http://codeforces.com/gym/100526 http://acm.hunnu.edu.cn/online/?action=problem&type=show& ...
- 【数论】【扩展欧几里得】Codeforces 710D Two Arithmetic Progressions
题目链接: http://codeforces.com/problemset/problem/710/D 题目大意: 两个等差数列a1x+b1和a2x+b2,求L到R区间内重叠的点有几个. 0 < ...
- [codeforces 200 E Tractor College]枚举,扩展欧几里得,三分
题目出自 Codeforces Round #126 (Div. 2) 的E. 题意大致如下:给定a,b,c,s,求三个非负整数x,y,z,满足0<=x<=y<=z,ax+by+cz ...
- Codeforces 7C 扩展欧几里得
扩展欧几里得是计算 ax + by = gcd(a,b) 的 x,y的整数解. 现在是ax + by + c = 0; 只要 -c 是 gcd(a,b) 的整数倍时有整数解,整数解是 x = x*(- ...
- AC Codeforces Round #499 (Div. 2) E. Border 扩展欧几里得
没想出来QAQ....QAQ....QAQ.... 对于一般情况,我们知道 ax+by=gcd(a,b)ax+by=gcd(a,b)ax+by=gcd(a,b) 时方程是一定有解的. 如果改成 ax+ ...
- Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) C.Ray Tracing (模拟或扩展欧几里得)
http://codeforces.com/contest/724/problem/C 题目大意: 在一个n*m的盒子里,从(0,0)射出一条每秒位移为(1,1)的射线,遵从反射定律,给出k个点,求射 ...
- Codeforces7C 扩展欧几里得
Line Time Limit: 1000MS Memory Limit: 262144KB 64bit IO Format: %I64d & %I64u Submit Status ...
- hdu 5512 Pagodas 扩展欧几里得推导+GCD
题目链接 题意:开始有a,b两点,之后可以按照a-b,a+b的方法生成[1,n]中没有的点,Yuwgna 为先手, Iaka后手.最后不能再生成点的一方输: (1 <= n <= 2000 ...
随机推荐
- Win内核原理与实现学习笔记2-现代操作系统的基本结构
1.操作系统本属于软件的范畴,但它需要紧密的跟硬件打交道,它为上层应用软件或应用系统提供了一层抽象,专门负责硬件资源的管理和分配.(应用程序不需要跟硬件打交道,它们利用操作系统提供的功能来实现各种任务 ...
- python 监听键盘事件pyHook
#coding=utf- import pyHook import pythoncom # 监听到鼠标事件调用 def onMouseEvent(event): if(event.MessageNam ...
- 第二章、URL与资源
1 URL统一资源定位符 URL 是浏览器寻找信息时所需的资源位置.通过 URL,人类和应用程序才能找到.使用并共享因特网上大量的数据资源.URL是作为URI的一个子集,URI是一类更通用的资源标识符 ...
- 使用log4j使某些java类的日志信息输出到指定日志文件中
Log4j 是 Apache 的一个开放源代码项目,通过使用 Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI 组件.甚至是套接口服务器.NT 的事件记录器.UNIX Syslog ...
- elasticsearch-6.4.3 集群搭建
1.准备三台服务器,已安装好es. 2.修改服务集群配置如下 使用命令: vi elasticsearch.yml 如下: cluster.name: myes ###保证三台服务器节点集群名称相同 ...
- [转][C#]AutoFac 使用方法总结
AutoFac使用方法总结:Part I 转自:http://niuyi.github.io/blog/2012/04/06/autofac-by-unit-test/ AutoFac是.net平台下 ...
- 阶段5 3.微服务项目【学成在线】_day04 页面静态化_19-页面静态化-模板管理-模板存储
因为没有界面,所以手动的通过操作数据库的方式来存储 比如说要存一个轮播图的模板 把自增的_id去掉 先用测试程序把文件存储到gridFS得到一个gridId,然后拿着这个文件的id 这样就添加好了这一 ...
- Ubuntu之安装PXE+Kickstart无人值守安装操作系统
CentOS安装PXE见 https://www.cnblogs.com/minseo/p/10774030.html 本文介绍Ubuntu系统安装pxe 1,环境查看 服务器ip地址:192.168 ...
- 通过命令行方式连接redis
1.首先安装redis客户端 yum install redis 2.连接 redis-cli -h host -p port -a password host:远程redis服务器host port ...
- golang struct组合,转型问题请教
type Action interface { OnHurt2(other Action) GetDamage() int } type Base struct { atk, hp int } fun ...