Problem F. Color
題意:長度爲n的一個連續串讓你染色,使得相鄰位置的顏色不能一樣,且串中恰好一共出現k種顏色,問若是你有m種顏色(m>=k),一共有多少種染色方法滿足給定條件.
我們易推得如果僅僅是要求相鄰位置的顏色不一樣那麼
我們再次設對於恰好出現種顏色的染色方法有種,那麼對於易得
我們再次設
那麼便可以得到這樣的一條等式
對於形如上式的的式子,我們都可以得到以下反演結果
以上都是二項式反演已知的固定反演形式,如果想要了解該等式的證明
可以參考lyf學長的證明
對於14年icpc西安區域賽的的這道題,若是已知這個結論這就是個秒A的水題了,然而今天打重現直接被這道題卡死了
問了問A了的隊友,說是感覺要容斥然後猜了一下結論就A了......
emmmm.......
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<limits.h>
#include<string.h>
#include<map>
#include<list>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
#define inf int(0x3f3f3f3f)
#define mod ll(1e9+7)
#define eps double(1e-6)
#define pi acos(-1.0)
#define lson root << 1
#define rson root << 1 | 1
ll n,m,k;
ll c[1000005];
ll inv[1000005];
ll powmod(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)
ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
void init()
{
inv[0]=1;
for(int i=1; i<=1000001; i++)
inv[i]=powmod(i,mod-2);
}
void init_c()
{
c[0]=1;
for(int i=1; i<=k; i++)
c[i]=c[i-1]*(k-i+1)%mod*inv[i]%mod;
}
ll C(ll n,ll m)
{
ll ans=1;
for(int i=1; i<=m; i++)
ans=ans*(n-i+1)%mod*inv[i]%mod;
return ans;
}
int main()
{
init();
cin.tie(0);
cout.tie(0);
int t;
init();
cin>>t;
for(int i=1; i<=t; i++)
{
cin>>n>>m>>k;
cout<<"Case #"<<i<<": ";
init_c();
ll ans=0;
ll flag=-1;
for(int i=k-1; i>=1; i--)
{
ans=(ans+flag*i*c[i]%mod*powmod(i-1,n-1)%mod+mod)%mod;
flag*=-1;
}
ans=(ans+k*c[k]*powmod(k-1,n-1))%mod;
ans=(ans*C(m,k)+mod)%mod;
cout<<ans<<endl;
}
}