版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/84888054
传送门
解析:
有点小骚的操作啊。。。
很是妙妙的一道题,最开始教练是抱着让我卡常的心态做的。然后根本优化不动。。。
一看AC了的代码。。。WOC真的很妙妙。
思路:
首先不要想 了,复杂度不对的。。。
那么怎么弄?
题目要求的东西就是
然后其实我们可以分别统计每个数的阶乘在实际操作中贡献的次数。
那么后缀和就是每个数实际上求出来的次数。
直接快速幂就行了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
cs int N=1000006;
int n,p;
int cnt[N];
int minpri[N];
int prime[N],pcnt;
inline void linear_sieves(int len=N-6){
for(int re i=2;i<=len;++i){
if(!minpri[i])minpri[i]=i,prime[++pcnt]=i;
for(int re j=1;i*prime[j]<=len&&j<=pcnt;++j){
minpri[i*prime[j]]=prime[j];
if(i%prime[j]==0)break;
}
}
}
inline int quickpow(int a,int b){
re int ans=1;
while(b){
if(b&1)ans=(ll)ans*a%p;
a=(ll)a*a%p;
b>>=1;
}
return ans;
}
int x[N],c[N],ans=1;
signed main(){
linear_sieves();
n=getint(),p=getint();
for(int re i=1;i<=n;++i)x[i]=getint();
for(int re i=1;i<=n;++i)c[i]=getint();
for(int re i=1;i<=n;++i)++cnt[c[i]],--cnt[x[i]],--cnt[c[i]-x[i]];
for(int re i=N-6;i>=1;--i)cnt[i]+=cnt[i+1];
for(int re i=N-6;i>1;--i)
if(cnt[i]){
if(minpri[i]==i)ans=(ll)ans*quickpow(i,cnt[i])%p;
else cnt[minpri[i]]+=cnt[i],cnt[i/minpri[i]]+=cnt[i];
}
printf("%d",ans);
return 0;
}