NOI模拟赛20200102 T1 排列【带限制排列计数】

题目描述:

在这里插入图片描述
n , k ≤ 1 0 18 , T ≤ 1 0 5 n,k\le10^{18},T\le10^5 n,k1018,T105

题目分析:

就算是让我自闭的题目,也是被某个人瞬间就切掉的大水题

考虑计算 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+n1m,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] );
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值