题意:n个白球.n-1台机器,第i台机器会将第(i,i+1)的球变为黑色.
一个操作序列为[1..n-1]的排列,其价值定义为n个球第一次变为黑色的时间.
2<=n<=1e6. 给出n,问所有操作排列,其价值总和模1e9+7 ?
首先1,n-1这两台机器必选,否则1,n不会变成黑色.
假设1=a[1]<a[2]<.....a[k] =n-1 那么a[i]-a[i-1]的间隔为1或者2. 设这两个个数为a,b.
可以得 a+b=k-1 , a+2b=n-2 解得b=n-k-1 那么从k-1个间隔中选b个为间隔2,就可以确定一个方案.方法数为C(k-1,n-k-1)
一个操作序列为[1..n-1]的排列,其价值定义为n个球第一次变为黑色的时间.
2<=n<=1e6. 给出n,问所有操作排列,其价值总和模1e9+7 ?
看了题解..先膜下rng_58.
计算价值<=k的排列有多少个? 那么价值为k的就是d[k]-d[k-1]首先1,n-1这两台机器必选,否则1,n不会变成黑色.
假设1=a[1]<a[2]<.....a[k] =n-1 那么a[i]-a[i-1]的间隔为1或者2. 设这两个个数为a,b.
可以得 a+b=k-1 , a+2b=n-2 解得b=n-k-1 那么从k-1个间隔中选b个为间隔2,就可以确定一个方案.方法数为C(k-1,n-k-1)
那么价值为k的排列总个数为: C(k-1,n-k-1) * k! * (n-1-k) !.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5,mod=1e9+7;
ll n,f[N];
ll powmod(ll x,ll n)
{
ll s=1;
while(n)
{
if(n&1)
s=(s*x)%mod;
n>>=1;
x=(x*x)%mod;
}
return s;
}
ll C(ll n,ll m)
{
if(n<m)
return 0;
ll a=f[n],b=(f[n-m]*f[m])%mod;
return (a*powmod(b,mod-2))%mod;
}
int main()
{
cin>>n;
f[0]=1;
for(int i=1;i<=n;i++)
f[i]=(f[i-1]*i)%mod;
ll res=0,pre=0;
for(int k=1;k<n;k++)
{
ll tk=(f[k]*f[n-1-k])%mod;
tk=(tk*C(k-1,n-k-1))%mod;
ll num=(tk-pre+mod)%mod;
res=(res+(num*k)%mod)%mod;
pre=tk;
}
cout<<res<<'\n';
return 0;
}
计数的时候可以先假定有序,算出其方案.然后在排列