P4104 [HEOI2014]平衡
题意转换:
杠杆的平衡条件为 (F1 imes L1 = F2 imes L2), 因为橡皮的质量相等,所以平衡的条件为:左边橡皮到重心的距离和等于右边橡皮到重心的距离和,
题目也就转化为,在重心左边选(i)个数,再在右边选((k-i))个点,到重心的距离和为(x)的方案数,也就是整数划分。
(f[x][i])表示选i个数,使和为x的方案数(也就是将x划分为i个不同数的方案数)。
可以看做有i个盒子,考虑盒子里有1和无1的情况 。
有1:(f[i-j][j-1]) 无1:(f[i-j][j])
那么(f[i][j] = f[i-j][j-1] + f[i-j][j])
#include <cstdio>
#include <iostream>
#define orz cout << "AK IOI" <<"
"
using namespace std;
const int maxk = 15;
const int maxn = 100010;
inline int read()
{
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 * 10 + ch - '0';ch = getchar();}
return x * f;
}
int T, n, k, p, f[maxn][maxk];
int main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
T = read();
while(T--)
{
n = read(), k = read(), p = read();
int ans = 0;
f[0][0] = 1;
for(int i = 1; i <= n * k; i++)
for(int j = 1; j <= i && j <= k; 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;
}
for(int i = 0; i <= k; i++)
for(int j = 0; j <= n * k; j++)
{
ans = (ans + f[j][i] * f[j][k - i] % p) % p;
if(i < k) ans = (ans + (f[j][i] * f[j][k - i - 1]) % p) % p;
}
printf("%d
", ans);
}
return 0;
}