[线性筛 质因数分解] 51Nod 1643 小Q的家庭作业



#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
typedef long long ll;

const int P=1e9+7;
const int N=10000005;

int prime[664580],num;
int vst[N],d[N];

inline void Pre(int maxn){
  for (int i=2;i<=maxn;i++){
    if (!vst[i])
      prime[++num]=i,d[i]=i;
    for (int j=1;j<=num && (ll)i*prime[j]<=maxn;j++){
      d[i*prime[j]]=prime[j];
      vst[i*prime[j]]=1;
      if (i%prime[j]==0)
	break;
    }
  }
}

inline ll Pow(ll a,ll b){
  ll ret=1;
  for (;b;b>>=1,a=a*a%P)
    if (b&1)
      ret=ret*a%P;
  return ret;
}

inline void Add(int &x,int c){
	x+=c; x=x>=P?x-P:x;
}

ll m;
int a,b,c;
int x[N],K,last,round;

int main(){
  ll ret;
  scanf("%lld%d%d%d%d",&m,&x[1],&a,&b,&c);
  Pre(c); cl(vst);
  K=1; vst[x[1]]=1;
  while (1){
    x[K+1]=((ll)a*x[K]+b)%c+1; K++;
    if (vst[x[K]]) break;
    vst[x[K]]=K;
  }
  last=vst[x[K]]-1; K--;
  round=K-last;
  cl(vst);
  ret=1; int tem=((m-last)/round)%P;
  for (int i=last+1;i<=K;i++){
    ret*=x[i],ret%=P;
    Add(vst[x[i]],tem);
  }
  ret=Pow(ret,(m-last)/round%(P-1));
  for (int i=1;i<=last;i++)
    Add(vst[x[i]],1),ret*=x[i],ret%=P;
  tem=(m-last)%round;
  for (int i=last+1;i<=last+tem;i++)
    Add(vst[x[i]],1),ret*=x[i],ret%=P;
  for (int i=c;i>1;i--)
    if (vst[i] && d[i]!=i)
      Add(vst[d[i]],vst[i]),Add(vst[i/d[i]],vst[i]);
  for (int i=1;i<=num;i++)
    ret*=(vst[prime[i]]+1),ret%=P;
  printf("%lld\n",ret);
  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值