=== ===
这里放传送门
=== ===
题解
通过打表找规律某种神秘的启示可以发现:
Fj|Fi⇒j|i
那么问题就变成了求约数个数还有约数平方和的问题
这两个东西都是可以线筛的
约数个数好办,和BZOJ1968的方法是一样的。
对于约数平方和,我们仍然考虑线筛三步走。
当x是质数的时候,它的约数的平方和就是
x2+1
,因为它只有
x
和1两个约数。
当已知
如果
x
原来就有
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const long long Mod=1000000007;
int m,q,a,b,c,prm[10000010],e[10000010],g[10000010];
long long f[10000010],d[10000010],A,B;
bool ext[10000010];
void get_prime(int N){
f[1]=d[1]=1;
for (int i=2;i<=N;i++){
if (ext[i]==false){
prm[++prm[0]]=i;
d[i]=2;e[i]=1;g[i]=1;
f[i]=((long long)i*i+1)%Mod;
}
for (int j=1;j<=prm[0];j++){
if ((long long)i*prm[j]>N) break;
ext[i*prm[j]]=true;
if (i%prm[j]==0){
e[i*prm[j]]=e[i]+1;
d[i*prm[j]]=(long long)d[i]/(e[i]+1)*(e[i]+2);
g[i*prm[j]]=g[i]%Mod;
f[i*prm[j]]=(f[g[i]]+(long long)f[i]*prm[j]%Mod*prm[j]%Mod)%Mod;
break;
}else{
e[i*prm[j]]=1;
d[i*prm[j]]=d[i]*d[prm[j]];
g[i*prm[j]]=i%Mod;
f[i*prm[j]]=(f[i]+(long long)f[i]*prm[j]%Mod*prm[j]%Mod)%Mod;
}
}
}
}
int main()
{
scanf("%d%d%d%d%d",&m,&q,&a,&b,&c);
get_prime(c);
for (int i=1;i<=m;i++){
long long tmp;
tmp=d[q]+((q&1)?1:0);
A=(A+tmp)%Mod;
tmp=f[q]+((q&1)?4:0);
B=(B+tmp)%Mod;
q=((long long)q*a+b)%c+1;
}
printf("%I64d\n%I64d\n",A,B);
return 0;
}
偏偏在最后出现的补充说明
找规律大法好