bzoj 4742 [Usaco2016 Dec]Team Building

Description
每年农夫约翰都会带着他的N只牛去集会上参加“你是最棒哒“的比赛。他的对手农夫保罗也带了M只牛去参加比赛
(1 ≤ N ≤ 1000, 1 ≤ M ≤ 1000)。每只牛都有自己的分数。两人会选择K只牛组成队伍(1 ≤ K ≤ 10),两队
牛在按分数大小排序后一一配对,并且约翰打败保罗当且仅当对于每一对牛,约翰的牛分数都比保罗的高。请帮助
约翰计算约翰打败保罗的方案数 mod 1000000009。两种方案不同,当且仅当约翰或保罗选择的牛的集合与另一种
方案不同。

Input
The first line of input contains N, M, and K. The value of K will be no larger than N or M.
The next line contains the N scores of FJ’s cows.
The final line contains the M scores of FP’s cows.

Output
Print the number of ways FJ and FP can pick teams such that FJ wins, modulo 1,000,000,009.

Sample Input
10 10 3
1 2 2 6 6 7 8 9 14 17
1 3 8 10 10 16 16 18 19 19

Sample Output
382

Solution

这种需要取模的计数一般都是能用dp做的。
我们对牛进行排序,就能发现子问题非常清晰了。
再对转移进行滚动与前缀和的优化。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
const int mod=1000000009;
int n,m,q,ans;
int a[1005],b[1005];
int f[1005][1005][2]; //到i牛,j牛,k组的方案数前缀和
int main()
{
    cin>>n>>m>>q;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=m;i++) scanf("%d",&b[i]);
    sort(a+1,a+n+1);
    sort(b+1,b+m+1);
    for(int k=1;k<=q;k++) 
    {
        for(int i=1;i<=n;i++) 
        for(int j=1;j<=m;j++) 
        if(a[i]>b[j]) 
        {
            if(k>1) f[i][j][1]=f[i-1][j-1][0]; else f[i][j][1]=1;
        }
        for(int i=1;i<=n;i++) 
        for(int j=1;j<=m;j++) 
        {
            f[i][j][0]=(f[i-1][j][0]+f[i][j-1][0])%mod;
            f[i][j][0]=((f[i][j][0]-f[i-1][j-1][0])%mod+mod)%mod;
            f[i][j][0]=(f[i][j][0]+f[i][j][1])%mod;
            f[i][j][1]=0;
        }
    }
    cout<<f[n][m][0];       
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值