bzoj2655calc 容斥+dp

2655: calc

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 322  Solved: 197
[Submit][Status][Discuss]

Description

  一个序列a1,...,an是合法的,当且仅当:
  长度为给定的n。
  a1,...,an都是[1,A]中的整数。
  a1,...,an互不相等。
  一个序列的值定义为它里面所有数的乘积,即a1a2...an。
  求所有不同合法序列的值的和。
  两个序列不同当且仅当他们任意一位不一样。
  输出答案对一个数mod取余的结果。

Input

  一行3个数,A,n,mod。意义为上面所说的。

Output

  一行结果。

Sample Input

9 7 10007

Sample Output

3611

HINT

数据规模和约定
  0:A<=10,n<=10。
  1..3:A<=1000,n<=20.
  4..9:A<=10^9,n<=20
  10..19:A<=10^9,n<=500。
  全部:mod<=10^9,并且mod为素数,mod>A>n+1

容斥法:
推荐blog
http://blog.csdn.net/qq_20669971/article/details/52790835
有一点不是很懂,就是那个统计f数组时阶乘那里

暴力法。

f[i][j]表示前i个格子,第i个格子填<=j的数的方案数
f[i][j]=f[i-1][j-1]*j+f[i][j-1]   复杂度O(nA)

第二维枚举A是肯定要TLE的,考虑优化
可以观察出这个东西可以表示成一个最高次为2n的多项式,未知数为j
那么就可以用拉格朗日求啦

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
#define N 605
using namespace std;
ll inv[N],c[N][N],fac[N],g[N],f[N],A,n,mod;
int main(){
    cin>>A>>n>>mod;
    fac[0]=1;inv[1]=1;
    for(int i=1;i<=510;i++)
    fac[i]=(fac[i-1]*i)%mod;
    for(int i=2;i<=510;i++)
    inv[i]=(1ll*(mod-mod/i)*inv[mod%i])%mod;
    for(int i=0;i<=n;i++)c[i][i]=c[i][0]=1;
    for(int i=1;i<=510;i++)
    for(int j=1;j<i;j++)
    c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
    g[0]=(A+1)%mod;g[1]=(1ll*A*(A+1)>>1)%mod;
    ll t=(A+1)*(A+1)%mod;
    for(int i=2;i<=n;i++){
        t=((A+1)*t)%mod;
        ll sum=(A+1)%mod;
        for(int j=1;j<i;j++)
        sum=(sum+1ll*c[i+1][j]*g[j]%mod)%mod;
        sum=(t-sum)%mod;
        sum<0?sum+=mod:1;
        g[i]=(sum*inv[i+1])%mod;
    }
    f[0]=1;f[1]=(1ll*(A+1)*A>>1)%mod;
    for(int i=2;i<=n;i++){
        f[i]=g[1]*f[i-1]%mod;
        ll fg=-1;
        for(int j=i-2;~j;j--){
            f[i]=(f[i]+1ll*fg*fac[i-1-j]%mod*c[i-1][i-1-j]%mod*g[i-j]%mod*f[j]%mod+mod)%mod;
            fg=-fg;
        }
    }
    cout<<f[n];
    return 0;
}
时间: 2024-08-03 11:33:52

bzoj2655calc 容斥+dp的相关文章

$bzoj2560$ 串珠子 容斥+$dp$

正解:容斥+$dp$ 解题报告: 传送门$QwQ$ $umm$虽然题目蛮简练的了但还是有点难理解,,,我再抽象一点儿,就说有$n$个点,点$i$和点$j$之间有$a_{i,j}$条无向边可以连,问有多少种方案可以连成一张联通图 显然考虑容斥呗?设$f_i$表示状态为$i$的点连成联通图的合法方案,$g_i$表示状态为$i$的点随便连边的所有方案 显然$g_i$可以先预处理出来?就等于$\prod_{u,v\in i}a_{u,v}$.然后$f_i$就等于$g_i$减去不合法的数量.不合法数量显然

[BZOJ4455][ZJOI2016]数星星(容斥DP)

4455: [Zjoi2016]小星星 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 707  Solved: 419[Submit][Status][Discuss] Description 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有n颗小星星,用m条彩色的细线串了起来,每条细 线连着两颗小星星.有一天她发现,她的饰品被破坏了,很多细线都被拆掉了.这个饰品只剩下了n?1条细线,但 通过这些细线,这颗小星星还是被串在一起,也就是这

【XSY3156】简单计数II 容斥 DP

题目大意 定义一个序列的权值为:把所有相邻的相同的数合并为一个集合后,所有集合的大小的乘积. 特别的,第一个数和最后一个数是相邻的. 现在你有 \(n\) 种数,第 \(i\) 种有 \(c_i\) 个.求所有不同的序列的权值的和. \(n\leq 50,c_i\leq 100\) 题解 考虑第一个数和最后一个数不相邻时怎么做. 记 \(g_{i,j}\) 为出现了 \(i\) 次的数分成 \(j\) 个集合,所有集合大小的乘积的和. \[ g_{i,j}=\sum_{k=1}^ig_{i-k,

AGC 005D.~K Perm Counting(容斥 DP 二分图)

题目链接 \(Description\) 给定\(n,k\),求 满足对于所有\(i\),\(|a_i-i|\neq k\)的排列的个数. \(2\leq n\leq 2000,\quad 1\leq k\leq n-1\). \(Solution\) 容斥.则\(Ans=\sum_{i=0}^n(-1)^ig(i)(n-i)!\),其中\(g(i)\)为至少有\(i\)个位置满足\(|a_i-i|=k\)的排列数. 考虑如何计算\(g(x)\).每个\(i\)向\(i+k\)和\(i-k\)连

hdu4624 Endless Spin (min-max容斥+dp)

min-max容斥: $$max\{a_i\}=\sum\limits_{S}(-1)^{|s|-1}min\{a_i|a_i \in S\}$$ 关于证明,可以把一个数$a$看作是集合$\{1...a\}$,于是max相当于取并集,min相当于取交集,就变成了普通的容斥 然后这道题就可以dp了 然而我一直被卡精度 以下代码大概是对的( 1 #include<bits/stdc++.h> 2 #include<tr1/unordered_map> 3 #define CLR(a,x

Jzzhu and Numbers CodeForces - 449D (容斥,dp)

大意: 给定集合a, 求a的按位与和等于0的非空子集数. 为了方便表述, 把每个数看成一个二进制位表示的集合, 例如十进制的$10$就看做集合$\{1,3\}$. 假设给定数的范围在$[0,2^{m})$内, 记$U=\{0,1,2,\cdots,m-1\}$. 首先根据容斥可以得到 $$ans=\sum\limits_{S\subseteq 2^{U}}(-1)^{|S|}(2^{f_S}-1) \tag{1}$$ 其中$f_S=\sum\limits_{T\in a}[T\supseteq

4455[Zjoi2016]小星星 容斥+dp

4455: [Zjoi2016]小星星 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 527  Solved: 317[Submit][Status][Discuss] Description 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有n颗小星星,用m条彩色的细线串了起来,每条细 线连着两颗小星星.有一天她发现,她的饰品被破坏了,很多细线都被拆掉了.这个饰品只剩下了n?1条细线,但 通过这些细线,这颗小星星还是被串在一起,也就是这

hud4336_容斥dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4336 题意:要集齐 n 张不同的卡片,给出每个卡片概率,问你集齐 n 张不同卡片要买卡片数量的期望 首先这里概率是同时取得,与不同步取得的概率有区别,很多人思想就局限在这里.至少得到一张A卡的期望值+至少得到一张B卡的期望值-至少得到一张卡的期望值==至少能得到A卡和B卡的期望值,这是两张卡的情况,这里我重点分析一下这一种情况:如0.1 0.4,我们要想至少得到第一张卡,那么就要满足1/0.1=10

Codeforces 1043F(容斥+dp)

题目链接 题意:是否存在选择方案使所选的数gcd=1 思路:f[i][j]表示选i个数gcd=j的方案数,cnt[i]表示包含因子i的数的个数, 则f[i][j]=C(cnt[j],i)-f[i][d],j|d,j<d #include <bits/stdc++.h> #define DBG(x) cerr << #x << " = " << x << endl; const int maxn = 3e5+5; cons