这道题首先需要进行题意转化。
比较考验开放思维...
题目链接。
题意
给你数字  与  要求构造一个长度为  的数列 ,满足以下条件:
 
 
询问有多少种方案数,对 
取模。
题解
首先我们知道这个序列是递增的,那么我们求出它的差分序列 ,特别地,。
这个时候,我们的要求就变成了:
不难发现,如果没有第一个条件,那么方案数很好算,就是 ,可以使用插板法推出来。
这个时候我们可以想到,将每一个  使用别的方法“表示”出来。
现在,我们对 
做带余除法,可以将  表达为 。
特别地,对于 ,我们令 。
那么现在,对于任意的一组 ,就有了唯一的  和  用来表示。
那么现在,条件转化为:
然后,我们枚举 ,考虑如何计算方案数。
首先  肯定是 ,不考虑。
不难发现,当  时,因为有
,而  又是  的倍数,所以 。
然后使用插板法,当 
时,方案数是 。
当  时,方案数是 。
所以现在,我们只需要知道 
的方案数即可,首先我们令 。
我们又知道,,所以直接可以得到方案数为 。
所以得到,最终答案为 
时间复杂度 。
代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 
 | #include<algorithm>#include<cstring>
 #include<cstdio>
 #include<vector>
 #include<queue>
 #include<map>
 #define inf 0x3f3f3f3f3f3f3f3fll
 const int mod=998244353;
 using namespace std;
 using ll=long long;
 using pli=pair<ll,int>;
 using pi=pair<int,int>;
 template<typename A>
 using vc=vector<A>;
 inline int read()
 {
 int s=0,w=1;char ch;
 while((ch=getchar())>'9'||ch<'0') if(ch=='-') w=-1;
 while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
 return s*w;
 }
 ll qow(ll a,int b)
 {
 ll ans=1;
 while(b)
 {
 if(b&1) ans=ans*a%mod;
 a=a*a%mod;
 b>>=1;
 }
 return ans;
 }
 ll inv[20000001];
 ll jc[20000001];
 int n,m;
 inline void init(int n)
 {
 jc[0]=1;
 for(int i=1;i<=n;i++) jc[i]=jc[i-1]*i%mod;
 inv[n]=qow(jc[n],mod-2);
 for(int i=n;i;i--) inv[i-1]=inv[i]*i%mod;
 }
 inline ll C(int a,int b)
 {
 if(b<0||a<b) return 0;
 return jc[a]*inv[b]%mod*inv[a-b]%mod;
 }
 int main()
 {
 n=read(),m=read();
 init(20000000);
 ll ans=0;
 for(int i=0;i<=m;i++)
 {
 ll val=(C(n,i-n)+C(n-1,i-n+1))%mod;
 ans=(ans+val*C((m-i)/3+n,n))%mod;
 
 }
 printf("%lld\n",ans);
 return 0;
 }
 
 | 
感谢观看!