『Raiden Ei』 Round 1A-振袖秋风问红叶题解

题目背景

海上漫游的日子是平淡的,所以万叶喜欢思考问题。

北斗总是喜欢提问万叶问题,但是万叶非常聪明,所以他想让你来回答北斗船长的问题。

题目描述

万叶进行了如下定义:

  • 对于一个排列 p,找到其最小的一个 i,满足 p 包含有长度为 1 到 i 的排列区间(详见提示说明),且不包含长度为 i+1 的排列区间,称之为 i 阶枫叶排列

北斗给了万叶若干个问题,每个问题形式如下:

给定 n 和 k,求出所有可能长度为 n 的排列中,有多少个排列是 k 阶枫叶排列。

由于这个答案可能很大,你只需输出答案对 998244353 取模后的结果。

输入格式

本题包含有多组测试数据。

第一行输入一个整数 T,表示数据组数。

对于每组数据,输入两个正整数 n,k,含义如上。

输出格式

对于每组数据,输出一行一个整数,表示所求的 k 阶枫叶排列数目。

输入输出样例

输入 #1复制

1
3 1

输出 #1复制

2

输入 #2复制

1
4 1

输出 #2复制

12

说明/提示

样例解释:

样例一:长度为 3 的一阶枫叶排列只有 (1,3,2),(2,3,1)。

数据范围:

本题采用捆绑测试

  • Subtask 1(20 pts):n≤10。
  • Subtask 2(30 pts):T≤103,n≤103。
  • Subtask 3(50 pts):无特殊限制。

对于所有测试数据,1≤T≤105,1≤n≤106,1≤k≤n。

为了避免用词上的歧义,在这里解释一下排列区间

例如在 (1,3,2,4) 中,(1,3,2) 就是一个长度为 3 的排列区间,因为它长度为 3,且恰好包含 1 到 3 的所有元素,而 (3,2,4) 和 (1,3) 则不是排列区间。

特别的,一个排列本身也是一个排列区间。

思路

首先,找出>=k的数量,容易发现,对于1~k可以前后加为2^(k-1),而剩余组合,为(n-k+1)!。

再减去>=k+1即可。

代码见下

#include<bits/stdc++.h>
using namespace std;
long long t,n,k,lk=1,kl=1,op=1,f[1000006],mod=998244353;
long long pow2(long long a1,long long b1,long long m1){
    long long kk1=1;
    while(b1>=1){
        if(b1%2==1){
            kk1*=a1;
        }
        b1/=2;
        a1*=a1;
        kk1%=m1;
        a1%=m1;
    }
    return kk1;
}
int main(){
    cin>>t;
    f[0]=1;
    for(int i=1;i<=1000000;i++){
        f[i]=f[i-1]*i;
        f[i]%=mod;
    }
    while(t--){
        cin>>n>>k;
        kl=((pow2(2,k-1,mod)*f[n-k+1])%mod);
        if(k!=n) op=((pow2(2,k,mod)*f[n-k])%mod);  
        else{
            op=0;
        }
        kl=(kl-op+mod)%mod;
        cout<<kl<<endl;
    }
	return 0;
}

posted @ 2025-10-05 19:27  bz02_2023f2  阅读(1)  评论(0)    收藏  举报  来源