• 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);
    }
    
  • 相关阅读:
    [NOIP2017]宝藏 子集DP
    [NOI2017]蔬菜 贪心
    hihoCoder#1698 : 假期计划 组合数
    KNIGHTS
    动态图连通性(线段树分治+按秩合并并查集)
    CF868F Yet Another Minimization Problem 分治决策单调性优化DP
    【POJ】【3308】Paratroopers
    【BZOJ】【3437】小P的牧场
    【BZOJ】【3156】防御准备
    【BZOJ】【1010】【HNOI2008】玩具装箱Toy
  • 原文地址:https://www.cnblogs.com/gmh77/p/12698406.html
Copyright © 2020-2023  润新知