【BZOJ2813】奇妙的Fibonacci(结论,线性筛)

结论:\(f_j|f_i\) 等价于 \(j|i\)

证明:(来自DTZ巨佬)

在这里插入图片描述
于是询问就变成了求一个数的因数个数和因数的平方和。

\(x=p_1^{k_1}p_2^{k_2}\cdots p_m^{k_m}\)

那么 \(x\) 的因数个数为 \(\prod\limits_{i=1}^m(k_i+1)\),因数平方和为 \(\prod\limits_{i=1}^m\sum\limits_{j=0}^{k_i}p_i^{2j}\)

用线性筛求解,有一个小 trick 是记录一个数 \(x\) 除尽其最小质因子后的数 \(nop(x)\),具体实现过程详见代码。

#include<bits/stdc++.h>

#define N 10000010

using namespace std;

namespace modular
{
	const int mod=1000000007;
	inline int add(const int x,const int y){return x+y>=mod?x+y-mod:x+y;}
	inline int dec(const int x,const int y){return x-y<0?x-y+mod:x-y;}
	inline int mul(const int x,const int y){return 1ll*x*y%mod;}
}using namespace modular;

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^'0');
		ch=getchar();
	}
	return x*f;
}

int q,a,b,c;
int cnt,prime[N];
int nop[N],s1[N],s2[N];
bool notprime[N];

void init()
{
	s1[1]=1,s2[1]=1;
	for(int i=2;i<=c;i++)
	{
		if(!notprime[i])
		{
			prime[++cnt]=i;
			nop[i]=1;
			s1[i]=2;
			s2[i]=add(mul(i,i),1);
		}
		for(int j=1,x;j<=cnt&&(x=(i*prime[j]))<=c;j++)
		{
			notprime[x]=1;
			if(!(i%prime[j]))
			{
				nop[x]=nop[i];
				s1[x]=mul(s1[nop[i]],add(s1[i/nop[i]],1));
				s2[x]=mul(s2[nop[i]],add(mul(s2[i/nop[i]],mul(prime[j],prime[j])),1));
				break;
			}
			nop[x]=i;
			s1[x]=mul(s1[i],s1[prime[j]]);
			s2[x]=mul(s2[i],s2[prime[j]]);
		}
	}
}

int main()
{
	q=read();
	int x=read();
	a=read(),b=read(),c=read();
	init();
	int ans1=0,ans2=0;
	while(q--)
	{
		ans1=add(ans1,add(s1[x],(x&1)));
		ans2=add(ans2,add(s2[x],(x&1)*4));
		x=(1ll*x*a+b)%c+1;
	}
	printf("%d\n%d\n",ans1,ans2);
	return 0;
}
/*
2
2 2 1 8
*/
posted @ 2022-10-28 19:40  ez_lcw  阅读(39)  评论(0)    收藏  举报