题面

题解

幸好咱不是在晚上做的否则咱就不用睡觉了……都什么年代了居然还会出高精的题……

先考虑如果暴力怎么做,令\(G(x)\)为\(F(n,k)\)的生成函数,那么不难发现$$GR(x)=\prod_{i=1}n(x+i)$$

也就是说如果把\(G(x)\)的系数反过来就是后面那个东西,所以对于\(n\leq 100000\)的数据直接分治\(FFT\)就行了。不过因为这里的模数不一定满足原根性质,所以要用三模数\(NTT\)或拆系数\(FFT\)(所以咱为了这题还特地去学了一下拆系数……)

我们要求的就是这个生成函数有多少项的系数在模\(p\)意义下不为\(0\),设\(n=a\times p+b\),那么生成函数可以写成$$\left(\prod_{i=1}p(x+i)\right)a\times \prod_{i=1}^b(x+i)$$

然后是一个比较神仙的结论:$$\prod_{i=1}^p(x+i)\equiv x(x^{p-1}-1)\pmod{p}$$

证:对于\(\prod_{i=1}^p(x+i)\),在模\(p\)意义下有且仅有\(p\)个根\(0,1,2,...,p-1\)

根据费马小定理,对于\(0<x<p\),\(x^{p-1}\equiv 1\pmod{p}\)恒成立,所以\(x(x^{p-1}-1)\)也有且仅有\(p\)个根\(0,1,2,...,p-1\)

因为\(Z_p[x]\)是唯一分解整环(咱也不知道这是个啥),所以这两个多项式相等

详细的别问咱咱连抽代是啥都不知道

于是式子就可以写成$$xa(x{p-1}-1)^a\times \prod_{i=1}^b(x+i)$$

把\((x^{p-1}-1)^a\)用二项式定理展开$$\sum_{i=1}ax{(p-1)\times i}(-1)^{a-i}{a\choose i}$$

考虑\({a\choose i}\),\(Lucas\)的过程中,本质上就是对\(a\)和\(i\)进行\(p\)进制分解,如果在某一步中\(a_k<i_k\),那么\({a_k\choose i_k}=0\),所以\({a\choose i}\equiv 0\)就代表着\(a,i\)的\(p\)进制分解过程中某一位上\(i\)大于\(a\)

设\(a=(a_0,a_1,...,a_k)_p\),那么满足\({a\choose i}\)在模\(p\)意义下不为\(0\)的\(i\)的个数就是\(\prod_{j=0}^k(a_j+1)\)

现在转过头回来考虑$$(x{p-1}-1)a\times \prod_{i=1}^b(x+i)$$

如果\(b<p-1\),那么左边式子里的非\(0\)项的次数都是\(p-1\)的倍数,那么任意两个这样的项乘上\(\prod_{i=1}^b(x+i)\)都不会重复,非\(0\)项的个数就是左右两边非\(0\)项个数的积,左边按上面的来,右边用分治\(FFT\)就行了

如果\(b=p-1\),那么\(\prod_{i=1}^b(x+i)=x^{p-1}-1\),只要计算\((x^{p-1}-1)^{a+1}\)就行了

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
const int N=5e5+5,P=998244353;
const double Pi=acos(-1.0);
struct cp{
double x,y;
cp(double xx=0,double yy=0){x=xx,y=yy;}
inline cp operator +(const cp &b)const{return cp(x+b.x,y+b.y);}
inline cp operator -(const cp &b)const{return cp(x-b.x,y-b.y);}
inline cp operator *(const cp &b)const{return cp(x*b.x-y*b.y,x*b.y+y*b.x);}
inline cp operator *(const double &b)const{return cp(x*b,y*b);}
}F[19][N],A[N],B[N],C[N],D[N],X[N],Y[N],Z[N],w[N];
int r[N],n,m,p,res;
void FFT(cp *A,int ty,int lim){
fp(i,0,lim-1)if(i<r[i])swap(A[i],A[r[i]]);
for(R int mid=1;mid<lim;mid<<=1)
for(R int j=0;j<lim;j+=(mid<<1))
for(R int k=0;k<mid;++k){
cp x=A[j+k],y=w[mid+k]*A[j+k+mid];
A[j+k]=x+y,A[j+k+mid]=x-y;
}
if(ty==-1){
reverse(A+1,A+lim);
double k=1.0/lim;fp(i,0,lim-1)A[i]=A[i]*k;
}
}
void calc(int ql,int qr,int d){
if(ql==qr)return F[d][0]=ql,F[d][1]=1,void();
int mid=(ql+qr)>>1;
calc(ql,mid,d),calc(mid+1,qr,d+1);
int lim=1,l=0;while(lim<=qr-ql+1)lim<<=1,++l;
fp(i,0,lim-1)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
for(R int i=1;i<lim;i<<=1)fp(k,0,i-1)w[i+k]=cp(cos(Pi*k/i),sin(Pi*k/i));
fp(i,mid-ql+2,lim-1)F[d][i]=0;
fp(i,qr-mid+1,lim-1)F[d+1][i]=0;
fp(i,0,lim-1){
A[i].x=(ll)(F[d][i].x+0.5)>>15,B[i].x=(ll)(F[d][i].x+0.5)&32767;
C[i].x=(ll)(F[d+1][i].x+0.5)>>15,D[i].x=(ll)(F[d+1][i].x+0.5)&32767;
A[i].y=B[i].y=C[i].y=D[i].y=0;
}
FFT(A,1,lim),FFT(B,1,lim),FFT(C,1,lim),FFT(D,1,lim);
fp(i,0,lim-1)
X[i]=A[i]*C[i],Y[i]=A[i]*D[i]+B[i]*C[i],Z[i]=B[i]*D[i]; FFT(X,-1,lim),FFT(Y,-1,lim),FFT(Z,-1,lim);
fp(i,0,lim-1){
F[d][i].x=((((ll)(X[i].x+0.5))%p<<30)+((ll)(Y[i].x+0.5)<<15)+((ll)(Z[i].x+0.5)))%p,F[d][i].y=0;
}
}
char s[N];int a[N],b[N],ans[N],top,st,ss,len,g;
void change(){
//高精转进制
while(top){
int res=0;st=top;
fp(i,1,st){
res=res*10+a[i];
b[i]=res/p,res%=p;
}
ans[++ss]=res;
//本轮的余数
int i=1;
while(i<=st&&!b[i])++i;
top=0;
fp(j,i,st)a[++top]=b[j];
}
}
void solve(){
scanf("%s%d",s+1,&p),len=strlen(s+1);
int k=1,res=0;
while(k<=len){
a[++top]=res/p,res%=p,res=res*10+s[k]-'0',++k;
}a[++top]=res/p,res%=p;
if(res!=p-1){
calc(1,res,0),g=0;
fp(i,0,res)if((ll)(F[0][i].x+0.5)%p!=0)++g;
}else ++a[top],g=1;
change();
fp(i,1,ss)g=1ll*g*(ans[i]+1)%P;
printf("%d\n",g);
}
int main(){
// freopen("testdata.in","r",stdin);
freopen("math.in","r",stdin);
freopen("math.out","w",stdout);
solve();
return 0;
}

jzoj6005. 【PKUWC2019模拟2019.1.17】数学 (生成函数+FFT+抽代+高精)的更多相关文章

  1. jzoj6004. 【PKUWC2019模拟2019.1.17】集合 (组合数学)

    题面 题解 这种题目就是要好好推倒 我们枚举最小的数是哪一个,那么答案就是\[Ans=\sum_{i=1}^nT^i{n-i\choose k-1}\] 因为有\[\sum_{i=p}^n{n-i\c ...

  2. 「NOIP模拟赛」数位和乘积(dp,高精)

    统计方案数,要么组合数,要么递推(dp)了. 这是有模拟赛历史以来爆炸最狠的一次 T1写了正解,也想到开long long,但是开错了地方然后数组开大了结果100->0 T3看错题本来简单模拟又 ...

  3. jzoj6002. 【PKUWC2019模拟2019.1.15】Permutation (组合数)

    题面 题解 设\(lim=(n-1)/2\)(这里是下取整),那么\(x\)位置的值最大不能超过\(lim\),而\(y\)处的值不能小于\(y\),于是有\[Ans=\sum_{i=1}^{lim} ...

  4. jzoj6001. 【PKUWC2019模拟2019.1.15】Mines (tarjan)

    题面 题解 我们把每个地雷向它能炸到的地雷连边,不难发现同一个强联通分量里的点只要一个炸全炸 那么我们缩点,首先所有入度为\(0\)的强联通分量中必须得选一个地雷炸掉,而入度不为\(0\)的强联通分量 ...

  5. 2019/01/17 基于windows使用fabric将gitlab的文件远程同步到服务器(git)

    觉得django项目把本地更新push到gitlab,再执行fabric脚本从gitlab更新服务器项目挺方便的,当然从本地直接到服务器就比较灵活. 2019/01/17 基于windows使用fab ...

  6. Sqlite && EF Code FIRST 终极解决方案 2019.5.17

    Sqlite && EF Code FIRST 终极解决方案 2019.5.17 包括根据模型自动生成数据库,初始化数据,模型改变时的自动数据迁移等 2019.12.25 更新 支持E ...

  7. loj6570 毛毛虫计数(生成函数FFT)

    link 巨佬olinr的题解 <-- olinr很强 考虑生成函数 考虑直径上点数>=4的毛毛虫的直径,考虑直径中间那些节点以及他上面挂的那些点的EGF \(A(x)=\sum_{i\g ...

  8. vj1010:高精乘+细心模拟

    这题的话思路挺简单的,主要是打一个高精乘,然后考虑一些细节的东西 码得挺少时间的,但是调错调了很久... 讲一下思路吧: 就是读入的时候,先把小数点去掉,mark一下小数点的位置 去掉小数点之后也就进 ...

  9. [jzoj 6080] [GDOI2019模拟2019.3.23] IOer 解题报告 (数学构造)

    题目链接: https://jzoj.net/senior/#main/show/6080 题目: 题意: 给定$n,m,u,v$ 设$t_i=ui+v$ 求$\sum_{k_1+k_2+...+k_ ...

随机推荐

  1. 【shell】常用的正则表达式

    一.校验数字的表达式 1 数字:^[0-9]*$ 2 n位的数字:^\d{n}$ 3 至少n位的数字:^\d{n,}$ 4 m-n位的数字:^\d{m,n}$ 5 零和非零开头的数字:^(0|[1-9 ...

  2. 你不得不知的几款常用的在线API管理工具

    在项目开发过程中,总会涉及到接口文档的设计编写,之前使用的都是ms office工具,不够漂亮也不直观,变更频繁的话维护成本也更高,及时性也是大问题.基于这个背景,下面介绍几个常用的API管理工具,方 ...

  3. python读取文件后切片

    from itertools import islice with open(“1.txt") as f: for a in islice(f,0,2): print(a)

  4. 写xml时候的一个坑

    <DOCTYPE scores[]>这一行总是显示错误,折腾了一晚上,后来无意错误在于:<!ELEMENT scores(student+)>应该写成:<!ELEMENT ...

  5. BZOJ 3251 树上三角形:LCA【构成三角形的结论】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3251 题意: 给你一棵树,n个节点,每个点的权值为w[i]. 接下来有m个形如(p,a,b ...

  6. 连接并同步windows下的git仓库

    1. 需求 电脑A和电脑B本来通过服务器同步工作目录.服务器时linux系统上有个裸仓库,不管在A上还是B上工作,工作完毕后使用git go与服务器仓库同步.A和B都是windows系统,在工作目录下 ...

  7. 疑难杂症:SQLServerAgent 当前未运行,因此无法将此操作通知它。

    日志信息:SQLServerAgent 当前未运行,因此无法将此操作通知它. (Microsoft SQL Server,错误: 22022) 确认问题之后,远程到服务器.按照以下步骤  1.打开计算 ...

  8. linux安装与卸载软件

    在ubuntu系统中,通常使用apt-get命令完成对软件的安装与卸载 安装的软件通常都放置在一些源中,国内有很多镜像源供下载使用,而系统设置的源保存在目录/etc/apt/sources.list文 ...

  9. 使用TortoiseGit同步代码到github远程仓库

    1.clone github上的代码仓库的URL 可以用HTTPS,SSH, or Subversion 2.同步push 到远程仓库时 要用 SSH地址,同生成SSH private key ,在g ...

  10. BZOJ - 4518: 征途(斜率优化,求N数划分为M区间的最小方差)

    注意初始化...等等补 #include<bits/stdc++.h> #define ll long long using namespace std; ; int q[maxn],he ...