题意:n个白球.n-1台机器,第i台机器会将第(i,i+1)的球变为黑色.
一个操作序列为[1..n-1]的排列,其价值定义为n个球第一次变为黑色的时间.
2<=n<=1e6. 给出n,问所有操作排列,其价值总和模1e9+7 ?
计算价值<=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)
一个操作序列为[1..n-1]的排列,其价值定义为n个球第一次变为黑色的时间.
2<=n<=1e6. 给出n,问所有操作排列,其价值总和模1e9+7 ?
看了题解..先膜下rng_58.
首先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; }
计数的时候可以先假定有序,算出其方案.然后在排列