• 2016CCPC 合肥--最大公约数//每一年通向它的路上,多少人折戟沉沙,多少人功败垂成,有人一战成名,有人从头再来。


    有这样一个有关最大公约数的函数:
    函数 f(x, y):


    {
    c=0
    当 y>0:
    {
    c +=1
    t = x % y
    x = y
    y = t
    }
    返回 c * x * x
    }


    给出三个正整数n,m,p,你需要计算:

    i=1nj=1mijf(i,j)

    对p取模的结果。

     1 #include <stdio.h>
     2 #include <iostream>
     3 #include <stack>
     4 #include <algorithm>
     5 #include <cstring>
     6 #include <vector>
     7 #include <cmath>
     8 #include <cctype>
     9 using namespace std;
    10 typedef long long ll;
    11 void in(int& n){scanf("%d",&n);}
    12 void in(ll& n){scanf("%I64d",&n);}
    13 const int N = 700;
    14 int gcd[N][N],num[N][N];
    15 int n,m,p;
    16 ll calc(ll x,ll y,ll tot,ll cnt)//tot 个数 cnt  分母
    17 {
    18     ll ans = (tot+1)*(x*y)+(tot+1)*tot/2*(y*y);//总和
    19     ll rd = y*y%cnt;
    20     ll ra = y*x%cnt;
    21     ll res = 0; //余数
    22     /*for(int i=0;i<=tot;++i){res+=(i*rd+ra)%cnt;}
    23     return (ans-res)/cnt%p;
    24     */ //复杂度太高
    25     for(int i=0;i<cnt;++i){
    26         res += (rd*i+ra)%cnt;
    27     }
    28     res = tot/cnt*res;
    29     for(int i=0;i<=tot%cnt;++i)
    30     {
    31         res += (rd*i+ra)%cnt;
    32     }
    33     return  (ans-res)/cnt%p;
    34 }
    35 void init()
    36 {
    37     for(int i=0;i<N;i++)
    38         for(int j=0;j<N;j++)
    39             if(i==0||j==0) gcd[i][j]=i+j;
    40             else if(i<j) gcd[i][j] = gcd[i][j%i];
    41                  else gcd[i][j] = gcd[i%j][j];
    42     for(int i=1;i<N;i++)
    43         for(int j=0;j<i;j++)
    44         {
    45             if(j==0) num[i][j] = 1;
    46             else num[i][j] = num[j][i%j] +1;
    47         }
    48 }
    49 int main()
    50 {
    51     init();
    52     int T;
    53     scanf("%d",&T);
    54     while(T--)
    55     {
    56         int ans = 0;
    57         scanf("%d%d%d",&n,&m,&p);
    58         for(int i=1;i<=m;i++)
    59             for(int j=0;j<i&&j<=n;j++)
    60             {
    61                 ans+=calc(j/gcd[i][j],i/gcd[i][j],(n-j)/i,num[i][j]);
    62                 ans%=p;
    63             }
    64         printf("%d
    ",ans);
    65     }
    66     return 0;
    67 }
    AC代码

    因为计算被m限制  变成了m个等差数列   求数列每一项/cnt 之和

    但是  但是  裸计算余数复杂度太大 

    所以    就是现场  看懂了题。。。也A不掉。。。。然后贴的这个余数 转化为cnt的计算方式。。。

    肯定是以cnt长度为循环。。。tot/cnt个循环 
    余下的tot%cnt 再求一次即可

    那么复杂度就降下来了

  • 相关阅读:
    搭建聊天机器人Bot Framework
    UsernamePasswordAuthenticationToken
    在JavaWeb项目中URL中字符串加密解密方案
    python自定义库文件路径
    difference between collection and association mapping in mybatis 3
    statpot:使用mongo+bootstrap+highcharts做统计报表
    Android仿微信SlideView聊天列表滑动删除效果
    Android Studio 运行、编译卡死的解决办法
    Android wear
    android实现json数据的解析和把数据转换成json格式的字符串
  • 原文地址:https://www.cnblogs.com/Geek-xiyang/p/6210685.html
Copyright © 2020-2023  润新知