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

来源:互联网 发布:知汇云软件 编辑:程序博客网 时间:2024/05/19 17:50

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 longusing 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--;    }}
2 0
原创粉丝点击