- 一个需要知道的结论是
,比较容易证明
于是,所以题目就是求
的前缀和
线筛一波,要特判的情况因为
,有些头凸
#include<bits/stdc++.h>
#define cs const
using namespace std;
typedef long long ll;
int read(){
int cnt = 0, f = 1; char ch = 0;
while(!isdigit(ch)){ ch = getchar(); if(ch == '-') f = -1; }
while(isdigit(ch)) cnt = cnt*10 + (ch-'0'), ch = getchar();
return cnt * f;
}
cs int Mod = 1e9 + 7;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
void Add(int &a, int b){ a = add(a, b); }
void Mul(int &a, int b){ a = mul(a, b); }
int sqr(int a){ return mul(a, a); }
cs int N = 1e7 + 50;
int Q, x, A, B, C, Sa, Sb;
int sig[N], sig2[N], mnp[N], vl[N], vl2[N], pc;
bool isp[N]; int prim[N/5];
void prework(int n){
sig[1] = sig2[1] = 1;
for(int i = 2; i <= n; i++){
if(!isp[i]){
prim[++pc] = i,
vl[i] = sig[i] = 2;
vl2[i] = sig2[i] = add(sqr(i),1);
mnp[i] = 1;
}
for(int j = 1; j <= pc; j++){
if(prim[j] * i > n) break;
int nx = prim[j] * i; isp[nx] = 1;
if(i % prim[j] == 0){
mnp[nx] = mnp[i];
vl[nx] = add(vl[i],1);
vl2[nx] = add(mul(sqr(prim[j]),vl2[i]),1);
sig[nx] = mul(sig[mnp[nx]],vl[nx]);
sig2[nx] = mul(sig2[mnp[nx]],vl2[nx]);
break;
}
mnp[nx] = i;
vl[nx] = 2;
vl2[nx] = add(sqr(prim[j]),1);
sig[nx] = mul(sig[i],sig[prim[j]]);
sig2[nx] = mul(sig2[i],sig2[prim[j]]);
}
}
}
int main(){
Q = read();
x = read(), A = read(), B = read(), C = read();
prework(C+1);
while(Q--){
if(x & 1) Add(Sa, 1), Add(Sb, 4);
Add(Sa, sig[x]);
Add(Sb, sig2[x]);
x = ((ll)x * A + B) % C + 1;
} cout << Sa << '\n' << Sb;
return 0;
}