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;
}