【NOIP2012模拟10.26】电影票
本题规律难找:
我们可以这么想:
我们先求出所有的方案,然后在去掉不正确的方案即可。
所有的方案:C(n,n+m)
不正确的方案:C(m-1,(n+1)+(m-1))=C(m-1,n+m)
于是答案便为:
C(n,n+m)- C(m-1,n+m)
我们化简化简(#^ . ^#)
=(n+m)!/n!/m!-(n+m)!/(m-1)!/(n+1)!
=(n+m)!(n+1)/(n+1)!/m!-(n+m)!*m/m!/(n+1)!
=(n+m)!*(n-m+1)/(n+1)!/m!
=(n+2)x…x(n+m)*(n-m+1)/m!
这样我想时间复杂度应当是大大减小了。
然后压压位,这样便肯定不会时超了!
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define mo 100000000000000
using namespace std;
struct node {int len; ll a[2010];}ans,c;
int n,m;
node cheng(node a,ll y)
{
c.len=a.len+2;
ll x=0;
for (int i=1;i<=c.len;i++)
{
c.a[i]=a.a[i]*y+x;
x=c.a[i]/mo,c.a[i]%=mo;
}
while (!c.a[c.len]) c.len--;
return c;
}
node divide(node a,ll y)
{
c.len=a.len;
ll x=0,h;
for (int i=c.len;i>0;i--)
{
h=(a.a[i]+x)%y;
c.a[i]=(a.a[i]+x)/y;
x=h*mo;
}
while (!c.a[c.len]) c.len--;
return c;
}
int main()
{
freopen("movie.in","r",stdin);
// freopen("movie.out","w",stdout);
scanf("%d%d",&n,&m);
// C(n,n+m)-C(m-1,n+m)
// =(n+m)!/m!/n!-(n+m)!/(m-1)!/(n+1)!
// =(n+2)*...*(n+m)*(n-m+1)/m!
ans.a[1]=n-m+1;ans.len=1;
for (int i=n+2;i<=n+m;i++)
ans=cheng(ans,i);
for (int i=2;i<=m;i++)
ans=divide(ans,i);
printf("%lld",ans.a[ans.len]);
for (int i=ans.len-1;i>0;i--)
printf("%014lld",ans.a[i]);
return 0;
}
转载需注明出处。