洛谷 P4031 [Code+#2]可做題2
題目大意
給定一個廣義斐波那契數列的第一項,和第二項的範圍,求滿足的數列的個數。
分析
先找一下的規律,設,則有:
多算幾個可以發現:。
那麼問題轉化爲求關於的同餘方程
在區間上的解的個數。
考慮移項:
將它轉化爲不定方程的形式:
於是直接套用擴展歐幾里得求出它的一個特解,再利用通解公式求出區間上解的個數即可。
注意比較大,求解和時要用矩陣乘法加速
參考代碼
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
ll p;
struct Matrix {
ll mat[2][2];
Matrix() {mat[0][0] = mat[1][1] = 1, mat[1][0] = mat[0][1] = 0;}
Matrix(int typ) {
if(typ == 0) mat[0][0] = mat[0][1] = mat[1][0] = mat[1][1] = 0;
if(typ == 1) mat[0][0] = 0, mat[1][0] = mat[0][1] = mat[1][1] = 1;
}
inline ll * operator [] (int x) {return mat[x];}
inline const ll * operator [] (const int &x) const {return mat[x];}
friend Matrix operator * (const Matrix &lhs, const Matrix &rhs) {
Matrix ret(0);
for(int k = 0; k < 2; k++)
for(int i = 0; i < 2; i++)
for(int j = 0; j < 2; j++)
ret[i][j] = (ret[i][j] + lhs[i][k] * rhs[k][j] % p) % p;
return ret;
}
};
Matrix QuickPow(Matrix a, ll k) {
Matrix ret;
while(k) {
if(k & 1) ret = ret * a;
a = a * a;
k >>= 1;
}
return ret;
}
ll i, l, r, m, k;
ll ExGCD(ll a, ll b, ll &x, ll &y) {
if(b == 0) {
x = 1, y = 0;
return a;
}
ll g = ExGCD(b, a % b, y, x);
y -= a / b * x;
return g;
}
int main() {
#ifdef LOACL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int _;
scanf("%d", &_);
while(_--) {
scanf("%lld %lld %lld %lld %lld %lld", &i, &l, &r, &k, &p, &m);
Matrix tmp(1);
tmp = QuickPow(tmp, k - 1);
i %= p;
m = (m - (tmp[0][0] % p * i) % p + p) % p;
ll x, y;
ll gcd = ExGCD(tmp[0][1], p, x, y);
if(m % gcd != 0) {
puts("0");
continue;
}
x *= (m / gcd), p /= gcd;
if(x >= 0) x = (x % p - p);
printf("%lld\n", (r - x) / p - (l - 1 - x) / p);
}
return 0;
}