zoukankan      html  css  js  c++  java
  • 51nod1352(exgcd)

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1352

    题意:中文题诶~

    思路:exgcd

    显然题目可以描述为:求a*x+b*y=n+1中满足  1 <= x,y <=n 的解数,

    可以先通过exgcd求出一组a*x+b*y=gcd(a, b)的解 x1, y1,那么对应的a*x+b*y=n+1的解就是x1*(n/gcd(a, b)), y1*(n/(gcd(a, b)),

    若能求出最小的x解的话,则每隔lcm(a, b), 隔lcm(a, b)出现一组满足条件的解,所以有ans=(n-1-x*a)/lcm(a,b) + 1;

    先令x=x1%b,要尽量使x小,所以将大于b的部分放到b*y中去;

    令temp=x*a, cc=lcm(a, b)

    则有:

      while(temp<1){
                temp+=cc;
            }
            while(temp>0){
                temp-=cc;
            }
            temp+=cc;// 第一个大于0的a*x

    将其直接化为公式计算:

      if(temp<1){
                k=ceil(double(1-temp)/cc);
                temp+=cc*k;
            }else{
                k=(temp-1)/cc;
                temp-=cc*k;
            }

    答案也就显而易见了,注意中间可能会爆int....

    代码:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <math.h>
     4 #define ll long long
     5 using namespace std;
     6 
     7 int exgcd(ll a, ll b, ll& d, ll& x, ll& y){
     8     if(b==0){
     9         x=1, y=0, d=a;
    10     }else{
    11         exgcd(b, a%b, d, y, x);
    12         y-=(a/b)*x;
    13     }
    14 }
    15 
    16 int main(void){
    17     int t;
    18     ll n, a, b;
    19     scanf("%d", &t);
    20     while(t--){
    21         scanf("%lld%lld%lld", &n, &a, &b);
    22         ll x, y, d;
    23         exgcd(a, b, d, x, y);
    24         if((++n)%d){ //a*x+b*y=c 当且仅当c=k*gcd(a,b)时有整数解
    25             printf("0
    ");
    26             continue;
    27         }
    28         x=x*(n/d)%b; //得到a*x+b*y=n+1的解,若x>b,将大于b的部分放到y*b中
    29         ll cc=a*b/d; //lcm(a,b)
    30         ll temp=x*a;
    31         // while(temp<1){
    32         //     temp+=cc;
    33         // }
    34         // while(temp>0){
    35         //     temp-=cc;
    36         // }
    37         // temp+=cc;// 第一个大于0的a*x
    38         ll k;
    39         if(temp<1){
    40             k=ceil(double(1-temp)/cc);
    41             temp+=cc*k;
    42         }else{
    43             k=(temp-1)/cc;
    44             temp-=cc*k;
    45         }
    46         if(temp>=n){
    47             printf("0
    ");
    48         }else{
    49             printf("%lld
    ", (n-temp-1)/cc+1);//前面给n加了1,但求出的b*y要<=n
    50         }
    51     }
    52     return 0;
    53 }
    View Code
  • 相关阅读:
    支付宝17年新春红包技术体系剖析
    从“扫月亮”到“扫福字”,扒一扒背后的支付宝AR框架体系
    【合集】支付宝春节红包背后的那些事——集五福,咻红包
    蚂蚁移动开发平台 mPaaS 3.0 智能化 + 生态化
    小程序 Serverless: 解放生产力,驱动研发效能提升
    深度解析:mPaaS 3.0全新组件
    vue--学习一
    .Net Mvc PagedList
    Integrated Security=SSPI
    IIS web site windows验证
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/6700046.html
Copyright © 2011-2022 走看看