【省選模擬】Fibonacci (線性篩)

在這裏插入圖片描述

  • 一個需要知道的結論是 gcd(fibn,fibm)=fibgcd(n,m)gcd(fib_n,fib_m)=fib_{gcd(n,m)},比較容易證明
    於是 fibmfibnmnfib_m|fib_n\Rightarrow m|n,所以題目就是求 σ0(n),σ2(n)\sigma_0(n),\sigma_2(n) 的前綴和
    線篩一波,要特判 22 的情況因爲 fib2=1fib_2=1,有些頭凸
#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;
}
發佈了651 篇原創文章 · 獲贊 98 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章