hdu5645 DZY Loves Balls && hdu5646 DZY Loves Partition

昨天打的bc,虽然只做出一道题,但还是贴出来吧。。。


这是第一个,一看小数据,二话不说暴力秒之。

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <string>
#include <sstream>
#include <ctype.h>
#include <cctype>
#include <string.h>
using namespace std;

const int N = 500;
const int INF = 10000000;

int main()
{
  //  freopen("in.txt", "r", stdin);
    int t, n, a[N];
    scanf("%d", &t);
    while(t --)
    {
        scanf("%d", &n);
        memset(a, 0, sizeof(a));
        for(int i = 0; i < n; i ++)
        {
            scanf("%d", &a[i]);
        }
        double num = 0;
        for(int i = 0; i < n; i ++)
        {
            for(int j = 0; j < n; j ++)
            {
                if(i == j) continue;
                if(a[j] < a[i]) num ++;
            }
        }
    //    printf("%lf\n", num);
        printf("%lf\n", num / ((n * (n - 1))));
    }
    return 0;
}


刚开始一看这题,我本来想先把n平分,因为是连续的,所以前后分别遍历加一。后来发现不对,第四组数据隔了两个,所以把最后一个数拿出来单独讨论,最后再讨论奇偶。这就是我和队友昨天想出的方法,还用了别的但是失败了,这个方法很遗憾最后也没敲出来。今天敲完提交,结果是WA,事实证明从算法上看就是错的。


这个是我没做出来看的房间里别的神牛的代码,真是太精辟了,我来说明下吧。


既然是连续的,刚开始就建立1 2 3 4 5...(共k个)的数学模型,求和之后从n减去,然后把剩下的平分为k份,从后往前依次加到这个数学模型上。余数另外存起来,拆成多个1,然后从后往前加上去,至于为毛不能从前往后,那是因为前面的数会和后面的数重复。真的只是数学模型的构建,受益匪浅哪。。。

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <string>
#include <sstream>
#include <ctype.h>
#include <cctype>
#include <string.h>

using namespace std;

const int N = 500;
const int MOD = 1000000007;

int main()
{
  //  freopen("in.txt", "r", stdin);
    int t;
    __int64 ans, n, k, buf;
    scanf("%d", &t);
    while(t --)
    {
        scanf("%I64d%I64d", &n, &k);
        buf = k * (1 + k) / 2;
        if(n < buf)  ans = -1;
        else
        {
            int p, q;
            ans = 1;
            p = n - buf;
            q = p % k;
            p = p / k;
            int j = q, ad;
            for(int i = p + k; i >= p + 1; i --)
            {
                if(j > 0) ad = 1;
                else ad = 0;
                ans *= (i + ad);
                ans = ans % MOD;
                j --;
            }
        }
        printf("%I64d\n", ans);
    }
    return 0;
}


下面是我的方法,事实证明最后一个数拿出来单独讨论,其就有可能与前面的数重复。如果用的个set之类的容器判重,那该数怎么办,要想变该数则就要动前面的数,然后就over了= =。所以这题我是真不会,受教了。

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <string>
#include <sstream>
#include <ctype.h>
#include <cctype>
#include <string.h>
using namespace std;

const int N = 500;
const int MOD = 1000000007;

int main()
{
  //  freopen("in.txt", "r", stdin);
    int t;
    __int64 ans, n, k, num, buf;
    scanf("%d", &t);
    while(t --)
    {
        scanf("%I64d%I64d", &n, &k);
        buf = k * (1 + k);
        if(n < buf / 2)  ans = -1;
        else
        {
            num = n / k;
            if(k % 2 == 0)
            {
                int ran = 1, coe = 1, sum = 0, form;
                ans = 1;
                while(1)
                {
                    if(k == 1) break;
                    form = (num + ran * coe);
                    ans *= form;
                    sum += form;
                    if(ans > 1000000000) ans = ans % MOD;
                    coe *= -1;
                    k --;
                    if(k % 2 == 0) ran ++;
                }
                int res;
                res = n - sum;
                ans *= res;
                if(ans > 1000000000) ans = ans % MOD;
            }
            else
            {
                int ran = 1, coe = 1, sum = num, form;
                ans = num;
                k = k - 1;
                while(1)
                {
                    if(k == 1) break;
                    form = (num + ran * coe);
                    ans *= form;
                    sum += form;
                    if(ans > 1000000000) ans = ans % MOD;
                    coe *= -1;
                    k --;
                    if(k % 2 == 0) ran ++;
                }
                int res;
                res = n - sum;
                ans *= res;
                if(ans > 1000000000) ans = ans % MOD;
            }
        }
        printf("%I64d\n", ans);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值