HDU - 4790(规律求和)

0 5 0 5 3 0

这组数据,把较长的区间放在前面。

这样一定有构成的和

0 1 2 3 4 5

    1 2 3 4 5 6

       2 3 4 5 6 7

           3 4 5 6 7 8

              4 5 6 7 8 9

                 5  6 7 8  9 10

前后各一个等差数列中间一个常数列,分开求和即可。

把较长的放前面,的原因, 这样一来,前后各一个lenb-1长度的等差,中间一个常数列,不用再分情况讨论。

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
#define rep(i,n) for(int i=0;i<int(n);i++)
#define rep1(i,x,y) for(int i=x;i<=(int)y;i++)
typedef long long ll;
int a,b,c,d,p,m;
int cal(int x){
   if(x==-1) return 0;
   return (x+1)/p+((x+1)%p>=(m+1) ? 1:0);
}
ll query(int x,int y){return cal(y)-cal(x-1); }
ll fir(int x,int y){
   if(x%p > m) return (ll)1+(p-x%p)+m;
   return (ll)1+(m-x%p);
}
ll gcd(ll a,ll b){return (b==0 ? a:gcd(b,a%b)); }
int main()
{
    int T,kase=1;
    scanf("%d",&T);
    while(T--){
       scanf("%d %d %d %d %d %d",&a,&b,&c,&d,&p,&m);
       if(b-a < d-c){ swap(a,c),swap(b,d);}
       ll ans = 0 ,x,y,x1,y1, lena = b-a+1,lenb=d-c+1;
       x = a+c; y=x+(lenb-1)-1;
       y1 = b+d; x1 = y1-(lenb-1)+1;
       int l = y+1, r = x1-1;
       ans += query(l,r)*lenb;
       ans += (fir(x,y)+fir(x,y)+(query(x,y)-1)*p)*(query(x,y))/2;
       ans += ((lenb-fir(x1,y1))*2-(query(x1,y1)-1)*p)*(query(x1,y1))/2;
       ll fenm = lena*lenb , g=gcd(fenm,ans);
       ans/=g; fenm/=g;
       printf("Case #%d: %I64d/%I64d\n",kase++,ans,fenm);
    }
    return 0;
}


 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值