HDU 5970 最大公约数
来源:互联网 发布:java仓库管理系统论文 编辑:程序博客网 时间:2024/06/11 07:11
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5970
题意:(中文题,,不用我说了吧.)
分析:
当时在比赛的时候并没有做出来,主要是时间不够,有点分心在其他题上,然后就水了.其实看到这种题,第一想法不用想太复杂,可能有暴力的方法,找规律!
看看数据范围
n <= 666,666,666, m <= 666, p <= 666,666,666
突破口必然在m上,那怎么用呢?
不可能暴力gcd和T的,这样必然超时,我们知道gcd(a,b)=gcd(b,a%b)
那又怎么样呢?那么给你一个提示,例如gcd(5,9)=gcd(16,9)
手写一下,你就发现确实是这样啊~!
不仅如此,f(5,9)=f(16,9)
那么我们就知道,如果以m为基数的话,那么对于所有的n,莫非就余0,余1,余2……余m-1
我们就可以这样做,然后就可以统计同余的有多少个,然后看一下规律,然后一大片的求,
就能在m^2的时间求出答案了..
别住,这个规律还是有问题啊.
它有向下取整,不可能把个i什么的拆出来,就必须一个个才行.就是(i*j)/f(i,j).
那就会出现多1,少1的情况..因为取整问题..
那么我们先暴力一段序列.看看数据有什么问题.
例如 9余5的所有数的f(i,j)
这明显有规律啊,循环节啊..
这下就懵逼了,循环节该怎么搞啊?
他们的差值又不一样..,这是个好问题,但是既然是循环节,肯定等差..
我也写了很久,然后我灵感来的猜出来的.
除去第一个f(y,m)=11;
他的差值循环节就是c
然后 d=c*(f(y,m)=11)(代表c倍的,余数y和m的f).
以上是我找到的规律,为什么是这样我就不太懂了,我也想了很久.
只要我们求出 (31+51+72+92)这段的初值,就可以用等差数列求循环节一整段
然后就是细节的处理了.
我的程序是卡过这题的,我也不知道为什么那么慢
算法复杂度在O(m^2*c) 我试过On(m^2*2c)都不行,因为这个循环节规律就是逼我在这种情况下找出来的.
/* Author:GavinjouElephant * Title: * Number: * main meanning: * * * */#include <iostream>using namespace std;#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>#include <sstream>#include <cctype>#include <vector>#include <set>#include <cstdlib>#include <map>#include <queue>//#include<initializer_list>//#include <windows.h>//#include <fstream>//#include <conio.h>#define MaxN 0x7fffffff#define MinN -0x7fffffff#define lson 2*k#define rson 2*k+1typedef long long ll;const ll INF=0x3f3f3f3f;const ll maxn=700;ll Scan()//读入整数外挂.{ ll res = 0, ch, flag = 0; if((ch = getchar()) == '-') //判断正负 flag = 1; else if(ch >= '0' && ch <= '9') //得到完整的数 res = ch - '0'; while((ch = getchar()) >= '0' && ch <= '9' ) res = res * 10 + ch - '0'; return flag ? -res : res;}void Out(ll a) //输出外挂{ if(a>9) Out(a/10); putchar(a%10+'0');}ll Fc[maxn][maxn];ll Fcx[maxn][maxn];void f(ll x,ll y){ ll tx=x,ty=y; ll c=0; while(y>0) { c+=1; ll t=x%y; x=y; y=t; } Fc[tx][ty]=c; Fcx[tx][ty]=c*x*x;}void init(){ for(ll j=1; j<=666; j++) { for(ll i=0; i<=j; i++) { f(i,j); } }}ll cas(ll x,ll y){ return (x*y)/Fcx[x%y][y];}int T;ll n,m,p;ll top;ll xhj[5000];ll Sum[5000];int main(){#ifndef ONLINE_JUDGE freopen("coco.txt","r",stdin); freopen("lala.txt","w",stdout);#endif init(); scanf("%d",&T); while(T--) { scanf("%I64d%I64d%I64d",&n,&m,&p); ll ans=0; ll d; for(ll j=1; j<=m; j++) { for(ll y=0; y<j; y++) { ll l=1-j-y; ll r=n-y; ll num=(r/j - l/j); if(y==0) { ans=(ans+num%p+(num*(num-1)/2)%p)%p; } else { //-->找循环节 if(num==0) continue; ll t=(num-1)/Fc[y][j]; ll tt=(num-1)%Fc[y][j]; ll s=cas(y,j); ans=(ans+s)%p; ll ss=0; ll sum=0; top=0; int i=y+j; for(top=0;top<Fc[y][j];top++,i+=j) { ll k=cas(i,j)-cas(i-j,j); sum=(sum+k)%p; xhj[top]=k; if(top==0){Sum[top]=k;} else {Sum[top]=Sum[top-1]+sum;} } if(t) { ss=(Sum[top-1]+s*top)%p; d=(Fc[y][j]*sum)%p; ans=(ans+(ss*t)%p+(t*(t-1)/2*d)%p)%p; s=(s+(sum*t))%p; } if(tt){ans=(ans+Sum[tt-1]+(s*tt)%p)%p;} } } } printf("%I64d\n",(ans+p)%p); } return 0;}
- HDU 5970 最大公约数
- HDU 5970 最大公约数
- hdu 5970 最大公约数
- HDU 5970 最大公约数(找规律)
- hdu 1222 最大公约数
- HDU 1014(最大公约数)
- HDU 最大公约数和最小公倍数
- hdu 1014 最大公约数
- hdu 4497 最大公约数和最小公倍数
- HDU 1722 Cake 最大公约数应用
- hdu 4497(最大公约数和最小公倍数)
- HDU-5970-最大公约数(合肥CCPC J题)-数学推导+找规律
- HDU hide handkerchief 最大公约数=1
- hdu 1108 最小公倍数(最大公约数、最小公倍数)
- hdu 2504 又见GCD(最大公约数)
- HDU 2028最小公倍数LCM 最大公约数GCD
- hdu 2503 1713 1108 最小公倍数&最大公约数
- hdu 5050 java程序求大数最大公约数
- LoadRunner模拟接口请求
- iOS10打开url方式
- HTTP请求简要记录
- Cache一致性协议之MESI
- unit 8
- HDU 5970 最大公约数
- 【Python】详解Python的装饰器
- Putty 无法连接腾讯云服务器
- 程序猿更友好的使用bootstrap弹出框
- R语言技巧:读取spss的sav格式文件
- Beetl学习总结(3)——高级功能
- 深入讲解WebView
- 玩无限消乐的设计示例(结束篇)增加情趣之音乐
- 输入输出流-Reader