我是超链接
定义Fibonacci数列为 F1=1 , F2=1,Fi=Fi−1+Fi−2(i>=3) 。
对于某一个数Fi,求有多少个Fj能够整除Fi (i可以等于j),以及所有满足条件的j的平方之和。
询问次数 ≤3∗106 , i≤107
这里有Fibonacci的几个柿子,用F表示:
1、 i mod prime[j] !=0
这时prime[j]是A的最小质因数且为1次
分析A的因数的组成,可以知道他由两部分组成,
一部分是i的所有因数 另一部分是i的所有因数各乘上prime[j]得到的
因此
g[A]=g[i]∗2
f[A]=f[i]∗(prime[j]2+1)
d[A]=i
2、 i mod prime[j] ==0
此时prime[j]是A的最小质因数 为e[i]+1次
d[A]=d[i]
令B=i/(prime[j]^e[i]) 即B是i除去最小质因数后得到的数d[i]
f[i]=f[B]∗∑e[i]k=0prime[j]2∗k
f[A]=f[B]∗∑e[i]+1k=0prime[j]2∗k
消去f[i]即得 f[A]=f[i]∗(prime[j]2)+f[B]
这里涉及到对于给定的i,B=i/(prime[j]^e[i])的计算,记为d[i]。
至此,我们得到了整个问题的O(n)预处理算法。
因为f[2]=1,所以如果q是奇数约数和要+1,平方和要+4
注意:q不是小于1e7的,ta可能等于1e7!预处理的时候一定要处理C的情况啊
#include
#define LL long long
using namespace std;
const int CC=1e7;
const int mod=1e9+7;
int q,C,e[CC+5],d[CC+5],g[CC+5],f[CC+5],prime[CC+5],num;
bool ss[CC+5];
//e[i]表示最小质因子次数,d[i]表示除去最小质因子之后的数
//g[i]表示含有约数个数,f[i]表示j的平方之和
void pre()
{
g[1]=1; f[1]=1;
for (int i=2;i<=C;i++)
{
if (!ss[i])
{
prime[++num]=i; e[i]=1; d[i]=1; g[i]=2; f[i]=(LL)i*i%mod+1;
}
for (int j=1;j<=num && prime[j]*i<=C;j++)
{
int A=prime[j]*i;
ss[A]=1;
if (i%prime[j]!=0)
{
e[A]=1; d[A]=i; g[A]=2*g[i]; f[A]=f[i]*((LL)prime[j]*prime[j]%mod+1)%mod;
}
else
{
e[A]=e[i]+1; d[A]=d[i]; g[A]=(g[i]/e[A])*(e[A]+1);
f[A]=((LL)f[i]*prime[j]%mod*prime[j]%mod+f[d[i]])%mod;
}
}
}
}
int main()
{
int Q,i,A,B,ans1=0,ans2=0;
scanf("%d%d%d%d%d",&Q,&q,&A,&B,&C);
pre();
A%=C; B%=C;
for (i=1;i<=Q;i++)
{
if (i>1) q=((LL)q*A+B)%C+1;
ans1=(ans1+g[q]+(q&1))%mod;
ans2=(ans2+f[q]+(q&1)*4)%mod;
}
printf("%d\n%d",ans1,ans2);
}