hdu 4970 Just Random(数学:推理)

来源:互联网 发布:java cmd运行 编辑:程序博客网 时间:2024/06/05 19:33

题意很简单,给出两个区间[a, b], [c, d]

在给出两个整数p, m

问你这两个区间各取一个数字使其和模p为m

这样的数占所有情况的比例


这个题学长说的思路,我敲的代码,真的给我搞的元气大伤!!

因为区间内的数是连续的,所以我们可以推知对于所有情况的集合S

可以把S分为3段,左侧一段从1递增,中间一段保持不变,右侧一段递减至1


接着就一步一步推,处理就好了

还是自己太弱,写了接近4个小时再见


代码如下(完美注释。。。):

#include <cstdio>#include <iostream>#include <algorithm>#define LL unsigned long longusing namespace std;LL gcd(LL a, LL b) {    return b ? gcd(b, a%b) : a;}int main(void) {    int T, a, b, c, d, p, m;    LL l_left, m_left, r_left, tmp;    LL l_right, m_right, r_right;    LL l_first, l_last, l_cnt, l_sum;    LL m_first, m_last, m_cnt, m_sum;    LL r_first, r_last, r_cnt, r_sum;    scanf("%d", &T);    for(int _=1; _<=T; ++_) {        scanf("%d%d%d%d%d%d", &a, &b, &c, &d, &p, &m);        l_left = a+c; l_right = a+c+min(b-a, d-c)-1;        m_left = l_right+1; m_right = b+d-min(b-a, d-c);        r_left = m_right+1; r_right = b+d;/*        printf("左边界: %lld -- %lld\n", l_left, l_right);        printf("中间边界: %lld -- %lld\n", m_left, m_right);        printf("右边界: %lld -- %lld\n", r_left, r_right);        puts("");puts("");puts("");puts("");*/        l_first = l_last = -1;        tmp = l_left+(m-l_left%p);        if(m >= l_left%p)            l_first = tmp;//左侧等差数列第一项        else l_first = tmp+p;        if(l_first > l_right || l_first < l_left)            l_first = -1;        tmp = l_right-(l_right%p-m);        if(m <= l_right%p)            l_last = tmp;//左侧等差数列最后一项        else l_last = tmp-p;        if(l_last < l_left || l_last > l_right)            l_last = -1;        if(l_first==-1 && l_last==-1) {            l_cnt = 0;            l_sum = 0;        } else if(l_first == -1) {            l_cnt = 1;            l_sum = l_last-l_left+1;        } else if(l_last == -1) {            l_cnt = 1;            l_sum = l_first-l_left+1;        } else {            l_cnt = (l_last-l_first)/p+1;//左侧符合条件的项数            l_sum = ((l_first-l_left+1) + (l_last-l_left+1))*l_cnt>>1;        }/*        printf("左侧等差数列满足条件边界:%lld -- %lld\n", l_first, l_last);        printf("左侧的个数和结果:%lld -- %lld\n", l_cnt, l_sum);        puts("");puts("");puts("");puts("");*/        m_first = m_last = -1;        tmp = m_left+(m-m_left%p);        if(m >= m_left%p)            m_first = tmp;        else m_first = tmp+p;        if(m_first > m_right || m_first < m_left)            m_first = -1;        tmp = m_right-(m_right%p-m);        if(m <= m_right%p)             m_last = tmp;        else m_last = tmp-p;        if(m_last < m_left || m_last > m_right)            m_last = -1;        if(m_last==-1 && m_first==-1) {            m_cnt = 0;            m_sum = 0;        } else if(m_first == -1) {            m_cnt = 1;            m_sum = m_left-l_left+1;        } else  if(m_last == -1) {            m_cnt = 1;            m_sum = m_left-l_left+1;        } else {            m_cnt = (m_last-m_first)/p+1;            m_sum = m_cnt*(m_left-l_left+1);        }/*        printf("中间等差数列满足条件边界:%lld -- %lld\n", m_first, m_last);        printf("中间的个数和结果:%lld -- %lld\n", m_cnt, m_sum);        puts("");puts("");puts("");puts("");*/        r_first = r_last = -1;        tmp = r_left+(m-r_left%p);        if(m >= r_left%p)            r_first = tmp;        else r_first = tmp+p;        if(r_first > r_right || r_first < r_left)            r_first = -1;        tmp = r_right-(r_right%p-m);        if(m <= r_right%p)             r_last = tmp;        else r_last = tmp-p;        if(r_last < r_left || r_last > r_right)            r_last = -1;        if(r_last==-1 && r_first==-1) {            r_cnt = 0;            r_sum = 0;        } else if(r_first==-1 && r_last!=-1) {            r_cnt = 1;            r_sum = (r_right-r_last+1);        } else if(r_last == -1 && r_first!=-1) {            r_cnt = 1;            r_sum = (r_right-r_first+1);        } else {            r_cnt = (r_last-r_first)/p+1;            r_sum = r_cnt*((r_right-r_first+1) + (r_right-r_last+1))>>1;        }/*                printf("右侧等差数列满足条件边界:%lld -- %lld\n", r_first, r_last);        printf("右侧的个数和结果:%lld -- %lld\n", r_cnt, r_sum);        puts("");puts("");puts("");puts("");*/        LL ans1 = l_sum+m_sum+r_sum;        LL ans2 = (LL)(b-a+1)*(d-c+1);        LL g = gcd(ans1, ans2);        if(g) {            ans1 /= g;            ans2 /= g;        }        if(ans1 == 0)             ans2 = 1;        printf("Case #%d: ", _);        cout << ans1 << "/" << ans2 << endl;    }    return 0;}


0 0
原创粉丝点击