CF660E. Different Subsets For All Tuples

题目大意

求长度为n的每项为[1,m]的所有数列的本质不同子序列个数和

n,m<=10^6

题解

洛谷黑题感觉过了,想想还是能想出来的

容斥很难搞所以直接算

对于每种子序列计算,只算在序列中第一次出现时算

“第一次”的定义:在序列上把查找的子序列一位位跳,每次跳最近的那个所得到的位置集合就是第一次出现的

设序列为a出现位置为b,则在b[i-1]+1~b[i]-1区间内都不能有a[i],只有m-1种方案,在b[i]以及>b[k]位置有m种方案

枚举b[k]和k可得

(ans=m^n+sum_{i=1}^{n}{sum_{j=1}^{i}{(m-1)^{i-j}C_{i-1}^{j-1}m^jm^{n-i}}})

考虑式子意义,就是[1,i-1]可以乘m或m-1,[i,n]乘n

合并一下就是

(ans=m^n+sum_{i=1}^{n}{(2m-1)^{i-1}m^{n-i+1}})

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define C(n,m) (jc[n]*Jc[m]%1000000007*Jc[(n)-(m)]%1000000007)
#define mod 1000000007
#define Mod 1000000005
#define ll long long
//#define file
using namespace std;

ll jc[1000001],Jc[1000001],w[1000001],p[1000001],P[1000001],ans;
int n,m,i,j,k,l;

int main()
{
	#ifdef file
	freopen("CF660E.in","r",stdin);
	#endif
	
	scanf("%d%d",&n,&m);
	if (m==1) {printf("%d
",n+1);return 0;}
	
	jc[0]=jc[1]=Jc[0]=Jc[1]=w[1]=p[0]=P[0]=1;p[1]=m+m-1;P[1]=m;
	fo(i,2,n)
	w[i]=mod-w[mod%i]*(mod/i)%mod,jc[i]=jc[i-1]*i%mod,Jc[i]=Jc[i-1]*w[i]%mod,p[i]=p[i-1]*(m+m-1)%mod,P[i]=P[i-1]*m%mod;
	
	fo(i,1,n)
	ans=(ans+p[i-1]*P[n-i+1])%mod;
	printf("%lld
",(ans+P[n])%mod);
}
原文地址:https://www.cnblogs.com/gmh77/p/12698406.html