ll f_cal(ll m, ll k){ ll ans = 0; ll up = (m + k - 1) / k; for (int c = 0; c <= up; ++c) { ans += CC(m - (c - 1) * (k - 1), c); ans %= mod; } ans %= mod; if (ans < 0) ans += mod; return ans; }
voidSolve(){ Cin(N, Q); map<ll, vector<ll> > mp; vector<vector<ll> > F(N + 2, vector<ll>(min(N, SQRT) + 2)); for (int k = 1; k <= min(N, SQRT); ++k) { F[0][k] = 1; for (int i = 1; i <= N; ++i) { F[i][k] = F[i - 1][k] + (i - k < 0 ? 1 : F[i - k][k]); F[i][k] %= mod; } } for (int _ = 1; _ <= Q; ++_) { ll x, k; Cin(x, k); ll up = (N + k - 1) / k; if (k > SQRT) { // 这个的计算是 k 越小,计算的越多的啊。 ll ans = f_cal(N, k) - (x - k < 0 ? 1 : f_cal(x - k, k)) * ( N - x - k + 1 < 0 ? 1 : f_cal(N - x - k + 1, k)); ans %= mod; if (ans < 0) ans += mod; write(ans); putc('\n'); } else { // 因此我们把这个 k 比较小的这个直接用数组存起来,后面直接输出即可 ll ans = 0; ans = F[N][k] - (x - k < 0 ? 1 : F[x - k][k]) * (N - x - k + 1 < 0 ? 1 : F[N - x - k + 1][k]); ans %= mod; if (ans < 0) ans += mod; write(ans); putc('\n'); } } }
template<typename T> voidCin(T &a){ T ans = 0; bool f = 0; char c = getc(); for (; c < '0' || c > '9'; c = getc()) { if (c == '-') f = 1; } for (; c >= '0' && c <= '9'; c = getc()) { ans = ans * 10 + c - '0'; } a = f ? -ans : ans; }
voidgetc(char &a){ char c = getc(); while (isspace(c)) { c = getc(); } a = c; }
namespace Comb { // 组合数加逆元,依赖于这个MAXN(初始化) vector<ll> frac, infrac; int ln = 1; bool initialized = false; // 在 k=0或者更小的时候 return 1 inline ll binpow(ll a, ll k){ ll res = 1; a %= mod; while (k > 0) { if (k & 1) res = (res * a) % mod; a = (a * a) % mod; k >>= 1; } return res; }
voidComb(int n){ ln = n; frac.assign(n + 5, 1); infrac.assign(n + 5, 1); for (int i = 1; i <= ln; ++i) { frac[i] = (frac[i - 1] * i) % mod; } infrac[ln] = binpow(frac[ln], mod - 2); for (int i = ln - 1; i >= 0; --i) { infrac[i] = (infrac[i + 1] * (i + 1)) % mod; } }
inline ll CC(ll n, ll k){ if (k < 0 || k > n) { #ifdef LOCAL cerr << "CC 组合数传入参数不合法,可能是传入顺序错了\n"; #endif return0; // Return 0 if k is out of range [0, n] } if (!initialized) { Comb(MAXN); initialized = true; } ll res = frac[n]; res = (res * infrac[n - k]) % mod; res = (res * infrac[k]) % mod; return res; }
inline ll PP(ll n, ll k){ if (k < 0 || k > n) { #ifdef LOCAL cerr << "PP 排列数传入参数不合法,可能是传入顺序错了\n"; #endif return0; } if (!initialized) { Comb(MAXN); initialized = true; } ll res = frac[n] * infrac[n - k]; res %= mod; return res; } }
usingnamespace Comb;
ll N, Q;
constexpr ll SQRT = 200;
ll f_cal(ll m, ll k){ ll ans = 0; ll up = (m + k - 1) / k; for (int c = 0; c <= up; ++c) { ans += CC(m - (c - 1) * (k - 1), c); ans %= mod; } ans %= mod; if (ans < 0) ans += mod; return ans; }
voidSolve(){ Cin(N, Q); map<ll, vector<ll> > mp; vector<vector<ll> > F(N + 2, vector<ll>(min(N, SQRT) + 2)); for (int k = 1; k <= min(N, SQRT); ++k) { F[0][k] = 1; for (int i = 1; i <= N; ++i) { F[i][k] = F[i - 1][k] + (i - k < 0 ? 1 : F[i - k][k]); F[i][k] %= mod; } } for (int _ = 1; _ <= Q; ++_) { ll x, k; Cin(x, k); ll up = (N + k - 1) / k; if (k > SQRT) { ll ans = f_cal(N, k) - (x - k < 0 ? 1 : f_cal(x - k, k)) * ( N - x - k + 1 < 0 ? 1 : f_cal(N - x - k + 1, k)); ans %= mod; if (ans < 0) ans += mod; write(ans); putc('\n'); } else { ll ans = 0; ans = F[N][k] - (x - k < 0 ? 1 : F[x - k][k]) * (N - x - k + 1 < 0 ? 1 : F[N - x - k + 1][k]); ans %= mod; if (ans < 0) ans += mod; write(ans); putc('\n'); } } }
signedmain(){ ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); #ifdef LOCAL cout.setf(ios::unitbuf); // 无缓冲流,方便我们调试 #endif