您的位置:首页 > 其它

[bzoj3026] 楼梯染色 解题报告

2016-09-11 16:12 218 查看
这题题意什么鬼呀。。

X

XX

XXX

XXXX

XXXXX

意思是形如这种的楼梯,然后要分成n块矩形。

显然每一行最后一个X会分属不同的矩形。

那么我们考虑最上面那个点所属的矩形,

X

XA

XAA

CCCC

CCCCC

那么其实它会把楼梯分成两部分,显然是不会有矩形跨越A和C的。因为假如说有矩形从A那里下来了,那么他显然不能包含最左面的C,那么最左边的C就无法被包含了。像这样:

X

XA

XOO

COOC

CCCCC

所以说这两部分是独立的。

那么就可以dp啦。

f(n)=∑i=1nf(i−1)∗f(n−i)f(0)=1

这就是经典的catlan数的式子啦,所以f(n)=(2nn)−(2nn−1)=(2nn)n+1

那么答案就是kf(n)

所以就又成了经典的组合数取模问题,对p-1分解质因数即可分别求组合数然后crt合并即可。

#include<cstdio>
#include<iostream>
using namespace std;
#include<algorithm>
#include<cstring>
const int p[]={2,3,11,2089,7253};
const int Mod=1000000123;
typedef long long LL;
LL power(LL prod,int x,int Mod)
{
//printf("power(%I64d,%d,%I64d)\n",prod,x,Mod);
LL ans=1;
for(;x;x>>=1)
{
if(x&1)ans=ans*prod%Mod;
prod=prod*prod%Mod;
}
return ans;
}
int cal_exp(int n,int Mod)
{
int ans=0;
for(;n;n/=Mod)ans+=n/Mod;
return ans;
}
const int P=10000;
LL factor[P];
LL fac(int n,int Mod)
{
factor[0]=1;
for(int i=1;i<Mod;++i)factor[i]=factor[i-1]*i%Mod;

LL ans=1;
for(;n;n/=Mod)ans=ans*power(factor[Mod-1],n/Mod,Mod)%Mod*factor[n%Mod]%Mod;

return ans;
}
LL C(int n,int m,int Mod)
{
LL ans;
if(cal_exp(n,Mod)>cal_exp(m,Mod)+cal_exp(n-m,Mod))ans=0;
else ans=fac(n,Mod)*power(fac(m,Mod),Mod-2,Mod)%Mod*power(fac(n-m,Mod),Mod-2,Mod)%Mod;
//printf("C(%d,%d,%d)=%I64d\n",n,m,Mod,ans);
return ans;
}
LL work(int n,int m,int Mod)
{
//puts("--------");
LL ans=0;
for(int i=5;i--;)ans=(ans+power(Mod/p[i],p[i]-1,Mod)*C(n,m,p[i]))%Mod;
//printf("C(%d,%d,%d)=%I64d\n",n,m,Mod,ans);
//for(int i=5;i--;)printf("%d:%I64d %d\n",p[i],ans%p[i],20%p[i]);
return ans;
}
int main()
{
freopen("bzoj3026.in","r",stdin);
freopen("bzoj3026.out","w",stdout);
int n,k;
while(~scanf("%d%d",&n,&k))cout<<power(k,((work(n*2,n,Mod-1)-work(n*2,n-1,Mod-1))%(Mod-1)+Mod-1)%(Mod-1),Mod)<<endl;
}


总结:

①一定要注意在指数的话应该是模φ(p)。

②除的时候一定要想清楚有没有逆元。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: