正题
题目链接:https://www.luogu.com.cn/problem/P4345
题目大意
TTT组询问,给出n,kn,kn,k求
∑i=0k(ni)\sum_{i=0}^{k}\binom{n}{i}i=0∑k(in)
对233323332333取模的值
1≤T≤105,1≤k≤n≤10181\leq T\leq 10^5,1\leq k\leq n\leq 10^{18}1≤T≤105,1≤k≤n≤1018
解题思路
因为模数很小,可以考虑用LucasLucasLucas定理,然后考虑怎么优化复杂度。
对于给出的n,kn,kn,k分成两个部分,第一部分是由kkk前面若干段长度为PPP的整段构成,这一部分的答案我们发现对于C⌊nP⌋⌊mP⌋×Cm%pn%pC_{\lfloor\frac{n}{P}\rfloor}^{\lfloor\frac{m}{P}\rfloor}\times C^{n\%p}_{m\% p}C⌊Pn⌋⌊Pm⌋×Cm%pn%p这两个值,后面那一个值的和是确定的,是∑i=1kCn%pk\sum_{i=1}^kC_{n\%p}^k∑i=1kCn%pk,前面那一部分的值我们可以递归下去计算。
然后第二部分是剩下的散段,这个部分我们也是自直接递归下去算就可以了
时间复杂度O(Tlogn)O(T\log n)O(Tlogn)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll P=2333;
ll n,k,t,S[P][P],C[P][P];
ll Lucas(ll n,ll k){if(!k)return 1ll;if(!C[n%P][k%P])return 0;return Lucas(n/P,k/P)*C[n%P][k%P]%P;
}
ll solve(ll n,ll k){if(k<0)return 0;if(n<P)return S[n][min(n,k)];ll tmp=solve(n/P,k/P-1)*S[n%P][n%P]%P;tmp=(tmp+solve(n%P,k%P)*Lucas(n/P,k/P)%P)%P;return tmp;
}
signed main()
{C[0][0]=S[0][0]=1;for(ll i=1;i<P;i++)for(ll j=0;j<=i;j++)C[i][j]=((j?C[i-1][j-1]:0)+C[i-1][j])%P;for(ll i=1;i<P;i++){S[i][0]=C[i][0];for(ll j=1;j<=i;j++)(S[i][j]=S[i][j-1]+C[i][j])%=P;}scanf("%lld",&t);while(t--){scanf("%lld%lld",&n,&k);printf("%lld\n",solve(n,k));}return 0;
}