####题目链接:
http://codeforces.com/contest/690/problem/D2
####题目大意:
一共有n块砖,筑成一道宽度为不超过c的墙,有多少的建筑方案?(n块不必要都用)
####结题思路:
枚举用的砖数,用的砖数为i时的建筑方案数为
(
i
i
+
c
−
1
)
\left(^{i+c-1}_{i}\right)
(ii+c−1)。
这有一个定理把n个相同的物品放入m个不同的盒子中(盒子可为空)的情况数
(
m
−
1
n
+
m
−
1
)
\left(^{n+m-1}_{m-1}\right)
(m−1n+m−1)。这个公式可这样理解有
n
+
m
−
1
n+m-1
n+m−1个物品,把其中
m
−
1
m-1
m−1个变成分割线,原来的n个物品被分成m部分。
所以原题就变成
∑
1
n
(
i
i
+
c
−
1
)
\sum_1^n\left(^{i+c-1}_{i}\right)
∑1n(ii+c−1),求组合数用卢卡斯定理,这题就解决了。
另外还有o(1)的解法,
a
n
s
=
(
m
i
n
(
n
,
c
)
m
a
x
(
n
,
c
)
)
−
1
ans=\left(^{max(n,c)}_{min(n,c)}\right)-1
ans=(min(n,c)max(n,c))−1,至于为什么还不知道。
#include<cstdio>
#include<cstdlib>
#define LL long long
const int mod=1000003;
LL f[700010]; //N为组合数的底数 的范围
void init(int p){
f[0] = 1;
for(int i = 1; i <= 700000; ++i)
f[i] = f[i-1] * i % p;
}
LL pow_mod(LL a, LL x, int p){
LL ret = 1;
a %= p;
while(x){
if(x & 1){
ret = ret * a % p;
--x;
}
else{
a = a * a % p;
x >>= 1;
}
}
return ret;
}
LL Lucas(LL n, LL k, int p){
LL ret = 1;
while(n && k){
LL nn = n % p, kk = k % p;
if(nn < kk) return 0;
ret = ret * f[nn] * pow_mod(f[kk] * f[nn - kk] % p, p - 2, p) % p;
n /= p;
k /= p;
}
return ret;
}
int main(){
int n,c;
LL ans=0;
init(mod);
scanf("%d%d",&n,&c);
for(int i=1;i<=n;++i){
ans=(ans+Lucas(i+c-1,i,mod))%mod;
}
printf("%I64d\n",ans);
//system("pause");
return 0;
}
本文解析了CodeForces平台上的D2题,通过枚举砖块使用数量的方法,结合组合数学中的卢卡斯定理,给出了求解不同建筑方案数目的算法实现。此外还提到了一个O(1)复杂度的解法。
430

被折叠的 条评论
为什么被折叠?



