题目描述:
n
,
k
≤
1
0
18
,
T
≤
1
0
5
n,k\le10^{18},T\le10^5
n,k≤1018,T≤105
题目分析:
(就算是让我自闭的题目,也是被某个人瞬间就切掉的大水题 )
考虑计算
S
(
n
,
m
)
S(n,m)
S(n,m)。
如果
n
+
n
−
1
≤
m
,
S
(
n
,
m
)
=
n
!
n+n-1\le m,S(n,m)=n!
n+n−1≤m,S(n,m)=n!
否则:
按一定的顺序确定排列,这个想法在计数中很常用。
Code:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int mod = 20000023;
int T,sf[mod],fac[mod]={1},ans;
LL n,k;
inline int Pow(int a,LL b){int s=1;for(;b;b>>=1,a=1ll*a*a%mod) if(b&1) s=1ll*s*a%mod;return s;}
inline int solve(LL n){
int q=1ll*(k+1)*k%mod;
return (1ll*(k+1)*(Pow(q,(n+1)>>1)-1)%mod+Pow(q,(n>>1)+1)-1)*Pow(q-1,mod-2)%mod;
}
int main()
{
freopen("permutation.in","r",stdin);
freopen("permutation.out","w",stdout);
for(int i=1;i<mod;i++) sf[i]=(sf[i-1]+(fac[i]=1ll*fac[i-1]*i%mod))%mod;
scanf("%d",&T);
while(T--){
scanf("%lld%lld",&n,&k);
if(n<=k+1) printf("%d\n",n<mod?sf[n]:sf[mod-1]);
else printf("%d\n", k<mod ? (sf[k-1]+1ll*fac[k]*solve(n-k))%mod : sf[mod-1] );
}
}