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

    3612: [Heoi2014]平衡

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 284  Solved: 220
    [Submit][Status][Discuss]

    Description

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

    Input

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

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

    Output

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

    Sample Input

    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

    Sample Output

    73
    1
    920
    8
    1
    4421
    2565
    0
    446
    2549

    HINT

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

    Source

    鸣谢佚名上传

    分析:

    可以把问题转化为整数划分问题...

    $f[i][j]$代表把$i$划分为$j$个互不相同的不超过$n$的数字的方案数,我们先不考虑$n$的限制,那么$f[i][j]=f[i-j][j]+f[i-j][j-1]$,如果最小的数字为$1$那么把最后一排去掉就会减少一个数字,否则就还是$j$个数字,现在加上了$n$的限制,我们从$f[i-j][j]$转移到$f[i][j]$的时候,如果最大的数字是$n$,那么转移过来就是$n+1$,所以要去掉包含$n+1$的方案数,就等价于去掉最后一列,也就是减去$f[i-n-1][j-1]$的方案数...

    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    //by NeighThorn
    using namespace std;
    
    const int maxn=10+5,maxm=100000+5;
    
    int n,k,p,ans,cas,f[maxm][maxn];
    
    signed main(void){
    	scanf("%d",&cas);f[0][0]=1;
    	while(cas--){
    		ans=0;
    		scanf("%d%d%d",&n,&k,&p);
    		for(int i=1;i<=n*k;i++)
    			for(int j=1;j<=k&&j<=i;j++){
    				f[i][j]=(f[i-j][j-1]+f[i-j][j])%p;
    				if(i>=n+1) f[i][j]=(((f[i][j]-f[i-n-1][j-1])%p)+p)%p;
    			}
    		for(int i=1;i<=n*k;i++)
    			for(int j=1;j<k;j++)
    				(ans+=f[i][j]*f[i][k-j]%p)%=p;
    		k--;
    		for(int i=1;i<=n*k;i++)
    			for(int j=1;j<k;j++)
    				(ans+=f[i][j]*f[i][k-j]%p)%=p;
    		if(!k)
    			ans++;
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

      


    By NeighThorn

  • 相关阅读:
    Poj 1742 Coins(多重背包)
    Poj 2350 Above Average(精度控制)
    求二进制数中1的个数
    Poj 1659 Distance on Chessboard(国际象棋的走子规则)
    Poj 2411 Mondriaan's Dream(压缩矩阵DP)
    Poj 2136 Vertical Histogram(打印垂直直方图)
    Poj 1401 Factorial(计算N!尾数0的个数——质因数分解)
    poj 2390 Bank Interest(计算本利和)
    Poj 2533 Longest Ordered Subsequence(LIS)
    Poj 1887 Testing the CATCHER(LIS)
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6485932.html
Copyright © 2011-2022 走看看