zoukankan      html  css  js  c++  java
  • Simple

    【问题描述】
    对于给定正整数 n,m,我们称正整数c为好的,当且仅当存在非
    负整数x,y,使得 n*x+m*y=c。
    现在给出多组数据,对于每组数据,给定 n,m,q,求[1,q]内有
    多少个正整数不是好的。
    【输入格式】
    第一行,一个整数T表示数据组数。
    接下来每行三个数,分别表示 n,m,q,即一组询问。
    【输出格式】
    对于每组数据,输出一行表示答案。
    【样例输入】
    2
    78 100 4
    70 3 34
    【样例输出】
    4
    23
    【数据范围及约定】
    对于30%的数据,n,m,q≤100。
    对于60%的数据,n,m,q≤10^5。
    对于100%的数据,n≤10^5,m≤10^9,q≤10^18,T≤10。

    分析:
    t1
    还没睡醒,打了一个暴力就跑了
    之后找了一个AC程序(没错,是yhzq的,%%%)
    一点一点摸索ta的思路

    题目可以看为是计算 n*x+y*m=c 中c的个数
    两个参数,不大好搞,咋办。。。
    设:n > m (之后的所有计算都是基于这个条件的)
    我们把n用m表示,
    n=k*m+t

    因为m<=100000, 所以t<100000
    我们开一个t数组,t[x]记录

    n的倍数中%m==x的最小数

    x的取值最多只有100000种,
    换句话说就是总有循环的一天

    好了,现在我们有了这个t数组
    要怎么计算答案呢
    首先,有一个显然的结论,
    如果从c符合条件,那么c的倍数都符合条件
    那我们只要找到最小的满足条件且不同的c,
    ans+=(q/c)
    很好,问题又简化一步

    这个t数组算出来不是用来看的啊,我们要好好利用

    假设我们有一个t[i]!=0
    我们要保证c中有n,
    (也可以没有,这时候i==0,也适用于以下的算法)
    c就要减去t[i] ,
    (t[i]是n的倍数中%m==i的最小值,可以视为是一种与其他的都互斥的情况)
    这样c中就一定包含n(的倍数)了,
    剩下的值就可以让m随意分配了,

    文字不明白,直接看式子:

    ans+=(q-t[i])/m+1;

    这里写图片描述

    tip

    诶??? 这个1是从哪来的???
    answer:q-t[i]中没有m也是一种方案啊
    (换句话说就是,n*x+y*m=c中y=0)

    最后输出的时候:

    printf(“%lld”,q-ans+1);

    诶??? 这个+1又是什么???
    answer:在t[i],i==0的时候我们的ans多加了一个1
    因为c的取值是[1,q],也就是说 n*x+y*m=c => x,y不同为0

    注意
    q-t[i]>=0不要忘了判断
    这里写图片描述

    这里写代码片
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define ll long long
    
    using namespace std;
    
    ll n,m,q;
    ll t[100010];
    
    void swp(ll &a,ll &b){ll r=a;a=b;b=r;return;}
    
    void doit()
    {
        int i;
        memset(t,-1,sizeof(t));   //余数
        for (i=0;;i++)
        {
            ll sum=n*i;
            if (t[sum%m]!=-1)  //循环了
               break;
            t[sum%m]=sum;  //%m==当前余数的最小n的倍数 
        } 
        ll ans=0;
        for (i=0;i<m;i++)  //t的取值:0~m-1
            if (t[i]!=-1&&(q-t[i]>=0))
               ans+=(q-t[i])/m+1;
        printf("%lld
    ",q-ans+1); 
    }
    
    int main()
    {
        int T;
        //freopen("simple.in","r",stdin);  
        //freopen("simple.out","w",stdout);
        scanf("%d",&T);
        while (T--)
        {
            scanf("%lld%lld%lld",&n,&m,&q);
            if (n<m) swp(n,m);  //n>m
            if (n>q&&m>q) printf("%lld
    ",q);
            else if (n>q&&m<=q) printf("%lld
    ",q-q/m);
            else doit();
        }
        return 0;
    }
  • 相关阅读:
    SQL Server 2012提供的OFFSET/FETCH NEXT与Row_Number()对比测试
    sql 知识点
    javascript基础拾遗——词法作用域
    Linux 软件包管理
    涉略spring
    WebReBuild年会流水记
    javascript面向对象学习笔记(一)——继承
    算法学习——动态规划策略入门
    编程之美读书笔记——2.3寻找水王
    Linux 引导流程解析
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673469.html
Copyright © 2011-2022 走看看