[bzoj3026] 楼梯染色 解题报告

这题题意什么鬼呀。。
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(i1)f(ni)f(0)=1

这就是经典的catlan数的式子啦,所以 f(n)=(2nn)(2nn1)=(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)
②除的时候一定要想清楚有没有逆元。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值