• 51nod1079(中国剩余定理)


    题目链接: http://www.51nod.com/onlineJudge/user.html#!userId=21687

    题意: 中文题诶~

    思路: 本题就是个中国剩余定理模板题,不过模拟也可以过,而且时间复杂度嘛~

    我们可以知道gcd得出两个数的最大公约在最坏的情况下(a, b是相邻的两个斐波拉契数)是O(logn)的, 同理可以知道exgcd也是O(lgn)时间复杂度,因此中国剩余定理时间复杂度是O(nlogn); 而模拟的话最坏的情况下需要O(n*x)的时间~本题两种算法都是15ms...

    这里给出一个关于gcd时间复杂度分析的博客: http://blog.csdn.net/zeroonet/article/details/53375313

    我们先说一下模拟.首先我们知道如果x%a=m的话, x=k*a+m.

    对于 x%a1=m1, 很显然x(min)=m, 如果再加一组条件 x%a2=m2, 若当前x(min)不满足条件2的话, 我们找下一个(我们可以想象满足条件1的数据升序排列)满足条件1的数据,即a1+m,再判断其是否满足条件2, 很显然我们只要地推下去就能找到同时满足条件1, 2的最小数据; 如果再加一个条件 x%a3=m3呢? 前面我们已经招到了满足条件1, 2的最小数据

    x(min), 若其不满足条件3话, 我们找下一个满足条件1, 2的数据, 即x(min)+lcm(a1, a2)(此题中ai与aj互质,所以直接相乘就好啦,并且由这里我们不难看出最坏情况下即每次加2时其时间复杂度为O(x)), 再判断其是否满足条件3, 最终我们可以招到同时满足三个条件的最小数;

    那么,很明显对于要满足n个这样的条件的答案我们也可以用这个方法求到啦~

    代码:

     1 #include <bits/stdc++.h>
     2 #define MAXN 20
     3 #define ll long long
     4 using namespace std;
     5 
     6 int main(void){
     7     int n;
     8     ll p[MAXN], m[MAXN], ans=0, gg=1;
     9     scanf("%d", &n);
    10     for(int i=0; i<n; i++){
    11         scanf("%lld%lld", &m[i], &p[i]);
    12     }
    13     ans=p[0];
    14     for(int i=0; i<n-1; i++){
    15         gg*=m[i];
    16         while(ans%m[i+1]!=p[i+1]){
    17             ans+=gg;
    18         }
    19     }
    20     printf("%lld
    ", ans);
    21     return 0;
    22 }

    那么中国剩余定理的模板呢~

    至于证明嘛, 暂时还没想到(望路过的大神教一下)~

    代码:

     1 #include <bits/stdc++.h>
     2 #define MAXN 20
     3 #define ll long long
     4 using namespace std;
     5 
     6 ll p[MAXN], m[MAXN];
     7 int n;
     8 
     9 void exgcd(ll a, ll b, ll& x, ll& y){  //exgcd求乘法取模运算的逆元
    10     if(!b){
    11         y=0, x=1;
    12         return;
    13     }else{
    14         exgcd(b, a%b, x, y);
    15         ll temp=x;
    16         x=y;
    17         y=temp-a/b*y;
    18     }
    19 }
    20 
    21 ll crt(void){
    22     ll M=1, ans=0;
    23     for(int i=0; i<n; i++){
    24         M*=m[i];
    25     }
    26     for(int i=0; i<n; i++){
    27         ll mi=M/m[i], x, y;
    28         exgcd(mi, m[i], x, y);
    29         ans=(ans+p[i]*x*mi)%M;
    30     }
    31     if(ans<0){
    32         ans+=M;
    33     }
    34     return ans;
    35 }
    36 
    37 int main(void){
    38     scanf("%d", &n);
    39     for(int i=0; i<n; i++){
    40         scanf("%lld%lld", &m[i], &p[i]);
    41     }
    42     printf("%lld
    ", crt());
    43     return 0;
    44 }
  • 相关阅读:
    python 软件目录规范
    生成器与迭代器
    第四周-第08章节-Python3.5-装饰器
    第三周-第18章节-Python3.5-函数式编程与函数不同
    第三周-第17章节-Python3.5-递归
    第三周-第16章节-Python3.5-局部变量与全局变量作用域
    第三周-第14章节-Python3.5-函数式编程
    JAVA发红包案例
    JAVA字符串
    JAVA关于字符串&&字符数组处理的小题目
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/6210204.html
Copyright © 2020-2023  润新知