zoukankan      html  css  js  c++  java
  • BZOJ3612: [Heoi2014]平衡

    时间限制: 10 Sec 内存限制: 256 MB
    提交: 376 解决: 297
    [提交][][]
    题目描述

    下课了,露露、花花和萱萱在课桌上用正三棱柱教具和尺子摆起了一个“跷跷板”。
    这个“跷跷板”的结构是这样的:底部是一个侧面平行于地平面的正三棱柱教具,
    上面 摆着一个尺子,尺子上摆着若干个相同的橡皮。尺子有 2n + 1 条等距的刻度线,
    第 n + 1 条 刻度线恰好在尺子的中心,且与正三棱柱的不在课桌上的棱完全重合。
    露露发现这个“跷跷板”是不平衡的(尺子不平行于地平面)。于是,她又在尺
    子上放 了几个橡皮,并移动了一些橡皮的位置,使得尺子的 2n + 1 条刻度线上都恰
    有一块相同质 量的橡皮。“跷跷板”平衡了,露露感到很高兴。
    花花觉得这样太没有意思,于是从尺子上随意拿走了 k 个橡皮。令她惊讶的事
    情发生了: 尺子依然保持着平衡!
    萱萱是一个善于思考的孩子,她当然不对尺子依然保持平衡感到吃惊,因为这
    只是一个 偶然的事件罢了。令她感兴趣的是,花花有多少种拿走 k 个橡皮的方法
    ,使得尺子依然保 持平衡?
    当然,为了简化问题,她不得不做一些牺牲——假设所有橡皮都是拥有相同质量的
    质点。但即使是这样,她也没能计算出这个数目。放学后,她把这个问题交给了她
    的哥哥/ 姐姐——Hibarigasaki 学园学生会会长,也就是你。当然,由于这个问题
    的答案也许会过于 庞大,你只需要告诉她答案 mod p 的值。
    输入

    第一行,一个正整数,表示数据组数 T(萱萱向你询问的次数)。

    接下来 T 行,每行 3 个正整数 n, k, p。
    输出

    共 T 行,每行一个正整数,代表你得出的对应问题的答案。

    样例输入

    10

    6 5 10000

    4 1 10000

    9 6 10000

    4 6 10000

    5 1 10000

    8318 10 9973

    9862 9 9973

    8234 9 9973

    9424 9 9973

    9324 9 9973
    样例输出

    73

    1

    920

    8

    1

    4421

    2565

    0

    446

    2549
    提示

    T <= 20,1 <= n <= 10000,1 <= k <= 10,2 <= p <= 10000,且 k <= 2n+1。

    题解

    题目可以简化成在[-n,n]中选出k个数,使其和为0
    设dp[i][j]表示j个正整数组成的和为i的方案数
    最后将i固定用乘法原理。
    

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    const int MAXN = 100005;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
        while(ch>='0' && ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    
    int T,n,k,p;
    int dp[MAXN][15];   //dp[i][j]表示选了i个数,和为j的方案数。 
    int ans;
    
    int main(){
        T=rd();
        while(T--){
            ans=0;
            n=rd();k=rd();p=rd();
            dp[0][0]=1;
            for(register int i=1;i<=n*k;i++)
                for(register int j=1;j<=k && j<=i;j++){
                    dp[i][j]=(dp[i-j][j]+dp[i-j][j-1])%p;
                    if(i>=n+1) dp[i][j]=((dp[i][j]-dp[i-n-1][j-1])%p+p)%p;
    //              cout<<i<<" "<<j<<" "<<dp[i][j]<<" "<<endl;      
                }
            for(register int i=0;i<=k;i++)
                for(register int j=0;j<=n*k;j++)    {
                    ans=(ans+dp[j][i]*dp[j][k-i]%p)%p;
                    if(i<k) ans=(ans+dp[j][i]*dp[j][k-i-1]%p)%p;
                }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    时间好快,转眼又一周
    八月第二周
    八月第一周
    经济学人:埃航失事:波音信誉遭到危机(2)
    1109. 航班预订统计 --前缀和 和差分
    99. 激光炸弹 --前缀和+暴力 + 动态规划
    1108. Defanging an IP Address
    【mybatis】学习笔记 3动态语句 foreach generator使用【 小心生成系统中的数据库 如uesr表 country表】
    【mybatis】学习笔记 2 动态代理 输入输出参数 关联查询
    【JSP学习笔记】1jsp入门
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9677029.html
Copyright © 2011-2022 走看看