JZOJ4868. 【NOIP2016提高A组集训第9场11.7】Simple

55 篇文章 0 订阅
17 篇文章 0 订阅

Description

这里写图片描述

Data Constraint

这里写图片描述

Solution

方法一:我们先来看一下不考虑重复时的的做法,对于一个固定的x,y的取值范围明显是[0, cnxm ]。所以我们枚举x,就可以算出对应的值。ans= qnx=0cnxm 这也是我考场的做法,但这并没有考虑重复的情况,所以是不对的。

现在我们来想想该如何去重。我们知道,当x> mgcd(n,m) 时,我们是可以将x减去 mgcd(n,m) ,然后y加上 ngcd(n,m) ,这样x又会再次小于 mgcd(n,m) ,与原来计算过的状态重复,这才导致了上面第一个算法时重复的情况,所以我们只要将x的范围缩小到[0, mgcd(n,m) ]即可,即ans= mgcd(n,m)x=0cnxm 。注意一下,在x=0时,ans要减一个1,因为不能出现x,y都为0的情况。

方法二:其实这条式子n*x+m *y=c,我们可以转化成n *x+(a *n+i)=c的形式。所以我们设出d[i]表示存在一个最小的m *y,使 (my)Modn=i 。那么对于一个d[i],显然 d[(d[i]+m)Modn]<=d[i]+m ,根据这条不等式,我们可以跑一下最短路,最后ans= n1x=0qd[x]n

Code

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
ll n,m,q,i,t,j,k,l,ans;
int gcd(ll a,ll b){
    ll r=a%b;
    while (r) a=b,b=r,r=a%b;
    return  b;
}
int main(){
//  freopen("simple.in","r",stdin);freopen("simple.out","w",stdout);
    freopen("data.in","r",stdin);
    scanf("%lld",&l);
    while (l){
        scanf("%lld%ld%lld",&n,&m,&q);
        ans=q;
        if (m>n) swap(n,m);
        t=m/gcd(n,m);
        for (i=0;i<t;i++){
            if (n*i>q) break;
            ans=ans-(q-n*i)/m;
            if (i) ans--;
        }
        printf("%lld\n",ans);
        l--;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值