題目描述
Description
Input
一行兩個整數n,k
Output
一行一個整數ans,代表答案,模1e9+
Sample Input
Sample Input 1
5 2
Sample Input 2
100 50
Sample Output
Sample Output 1
12
Sample Output 2
400502129
Data Constraint
題解
設f[i]表示至少染色i次後能全部染黑的方案數
那麼答案
因爲每種排列一共被算了(手賤次數+1)次,所以最後要減去排列數
k=1 or k=n
答案爲0
k*2≥n
頭尾放完後中間隨便放,因爲都能染黑
k=2
枚舉i,組合數隨便算
時間:O(n)
k≥1000
f[i]不好直接算
容斥,對於每個i求出有至少j個間隔≥m的方案,隨便算算
這樣剩下的只有間隔<k的方案
證明:
設有k個間隔≥k
那麼被算的次數=
楊輝三角中,只有第一行奇數和-偶數和=1,其餘都爲0(當前行的奇/偶和=上一行奇+偶,初始奇=1歐=0)
時間:O(n2/k),過不了30%所以要特殊處理
code
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define mod 1000000007
#define Mod 1000000005
using namespace std;
long long jc[1000001];
long long Jc[1000001];
long long w[1000001];
long long f[1000001];
int n,m,i,j,k,l;
long long ans;
long long qpower(long long a,int b)
{
long long ans=1;
while (b)
{
if (b&1)
ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
long long C(int n,int m)
{
return jc[n]*Jc[m]%mod*Jc[n-m]%mod;
}
int main()
{
freopen("jian.in","r",stdin);
freopen("jian.out","w",stdout);
scanf("%d%d",&n,&m);
if (n==m)
{
printf("0\n");
return 0;
}
jc[0]=1;jc[1]=1;
Jc[0]=1;Jc[1]=1;
w[1]=1;
fo(i,2,n)
{
w[i]=(long long)mod-(mod/i)*w[mod%i]%mod;
jc[i]=jc[i-1]*i%mod;
Jc[i]=Jc[i-1]*w[i]%mod;
}
if (m==1)
{
printf("0\n");
return 0;
}
if (m+m>=n)
{
f[0]=jc[2]*jc[(n-m+1)-2]%mod;
fo(i,1,(n-m+1)-2)
f[i]=C((n-m+1)-2,i)*jc[i+2]%mod*jc[(n-m+1)-2-i]%mod;
}
else
if (m==2)
{
fo(i,(n-m-m-1)/m+1,n-m-1)
f[i]=C(i+1,n-m-1-i)*jc[i+2]%mod*jc[(n-m+1)-(i+2)]%mod;
}
else
{
fo(i,(n-m-m-1)/m+1,n-m-1)
{
fd(j,min(i+1,(n-m-1-i)/m),0)
if (!(j&1))
f[i]=(f[i]+C(i+1,j)*C(n-m-1-i-j*m+(i+1)-1,(i+1)-1)%mod)%mod;
else
f[i]=(f[i]-C(i+1,j)*C(n-m-1-i-j*m+(i+1)-1,(i+1)-1))%mod;
f[i]=f[i]*jc[i+2]%mod*jc[(n-m+1)-(i+2)]%mod;
}
}
ans=f[0];
fd(i,n-m-1,1)
ans=(ans+f[i])%mod;
ans-=jc[n-m+1];
printf("%lld\n",(ans%mod+mod)%mod);
}