YZOJ-P3238-电梯
百度百科
姿势水平还要提起来。
题意描述:
问题一:对
x,y∈N
且
ax+by<=a×b
, 求
ax+by
的取值个数。
问题二:对
x,y∈N
,询问一个
c
,使
考场情况:
写了个广搜+哈希,水过55分………
正解:线性规划
问题一:
→ 发现不同点对 (x,y) 可能出现 ax+by 相同。
推exgcd:
x1=y2,y1=x2−[ab]y2
通解:
x=xo+bgcd(a,bt,t∈Z
则在
[0,bgcd(a,b))
内点到权值映射为一对一。
→
求这部分面积。
套个梯形面积公式就好…但是写挂了。原因是没有处理到上方线上的点,改成个割补法竟然过了。
问题二:
考虑 a,b大小。
若a=b自然很好处理。
若a>b,则使b个数尽可能少,就可以构造最优解。
由
x=xo+bgcd(a,bt,t∈Z
对
x0
进行取模等操作,构造x的最小非负整数解,并推出y即可。
#include<cstdio>
#include<algorithm>
#define R register
#define ll long long
using namespace std;
int gcd(R ll a,R ll b)
{
R ll k;
while(b!=0)
k=a,a=b,b=k%b;
return a;
}
void exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0){x=1,y=0;return;}
exgcd(b,a%b,x,y);
ll k=x;
x=y,y=k-(a/b)*y;
}
int main()
{
//freopen("2.txt","r",stdin);
R ll x0,y0,x,y;
R ll a,b,c,g,k,m;
R int Q;
scanf("%lld%lld%d",&a,&b,&Q);
if(a>b)swap(a,b);
g=gcd(a,b);
k=a*b/g-( (a/g-1)*(b/g-1)>>1 )+1;
printf("%lld\n",k);
exgcd(a,b,x0,y0);m=b/g;
while(Q--)
{
scanf("%lld",&c);
if(c%g!=0){printf("-1\n");continue;}
k=c/g%m;x=x0*k;
x=(x%m+m)%m;
y=(c-a*x)/b;
if(y<0){printf("-1\n");continue;}
printf("%lld\n",x+y);
}
return 0;
}
我的线性规划还要加强。要尽可能多参加网上的训练,尽能力的刷题了。