uoj
题目描述自己看去吧(
题解时间
首先看到 $ p $ 这么小还是质数,第一时间想到 $ lucas $ 定理。
注意 $ lucas $ 定理的另外一种写法是将数转换为 $ p $ 进制后计算$ C_{n}^{m} = \Pi C_{a_i}^{b_i} $
所以考虑对于 $ l-1 $ 和 $ r $ 各进行一次数位 $ dp $ 。
$ dp[i][j] $表示从低位起算到 $ i $ 位计算结果取模后为 $ j $ 且保证是在合法范围以内的方案数
$ dg[i][j] $ 表示从低位起算到 $ i $ 位计算结果取模后为 $ j $ 且不保证是在合法范围以内的方案数
转移方法:
对于计算到某一位 $ i $
$ n $ 已经给定,也就是说 $ b_i $ 已经确定
所以枚举 $ x $ 值在这一位对应的 $ a_i $ 设为 $ k $ ,设 $ C_{k}^{b_i}=g $
转移:
$ dg[i][jg mod p]+=dg[i-1][j] $
$ dp[i][jg mod p]+=dg[i-1][j](k $ dp[i][jg mod p]+=dg[i-1][j](k=a_{i_{max}}) $ 时间复杂度$ p^{2}logn $。 这个暴力好像是有50分。 然后考虑优化。 ~~ (这么毒瘤咋考虑出来的啊) ~~ 上式中的 $ jg $ 可以考虑优化掉。 这时就如毒瘤的数学题一样,我们看到p是质数,考虑直接用指标把它降维就好了。。。(啥?) 还是考虑上面的dp方程。 我们现在枚举到i位,用上面第一个转移式为例。 设 $ f[x]=\Sigma[C_{k}^{b_i}==x] $ 那么转移式变成一个乘法卷积 $ dg^{'}[i]=\Sigma dg[j] * \Sigma f[g] * [jg mod p == i] $ 上指标之后$ dg^{'}[i]=\Sigma dg[j] * \Sigma f[g] * [(ln[j]+ln[g]) mod \phi(p) == i] $ 然后上NTT。 (markdown的公式咋回事啊空格都打不出来) >1]>>1)|((len>>1)*(i&1));
//-----------------------------------------------------------------------------------------------------
//just get the g and ln of p
{
int tmp=phi;
for(int i=2;i*i<=tmp;i++)if(tmp%i==0)
{
pri[++pri[0]]=i;
while(tmp%i==0) tmp/=i;
}
if(tmp!=1) pri[++pri[0]]=tmp;
for(int i=1;i >=1;
}
return ret;
}
void ntt(lint *f1,int tp)
{
for(int i=0;i#include