Description:


\(1<=n,k<=1e5,mod~1e9+7\)

题解:


考虑最经典的排列dp,每次插入第\(i\)大的数,那么可以增加的逆序对个数是\(0-i-1\)。

不难得到生成函数:

\(Ans=\prod_{i=0}^{n-1}(\sum_{j=0}^ix^j)[x^k]\)

\(=\prod_{i=1}^{n}{1-x^i\over 1-x}[x^k]\)

分母是一个经典的生成函数:

\({1\over 1-x}^n=(\sum_{i>=0}x^i)^n=\sum_{i>=0}C_{i+n-1}^{n-1}\)

那么问题就变为了求:

\(\prod_{i=1}^{n}{1-x^i}\)的前k项。

考虑利用整数划分dp,相当于把k划分成若干不同且<=n的数和,系数是\((-1)^{数的个数}\)。

不难得出dp:

设\(f[i][j]\)表示已经划分了i个数,和为j的所有方案系数和。

转移\(f[i][j]=f[i][j-i]-f[i-1][j-i]+f[i-1][j-(n+1)]\)

由于\(i<=\sqrt {2k}\),所以复杂度是\(O(k\sqrt k)\)。

另一种多项式exp的做法:

不妨对这个式子进行ln最后再exp回去。

我们知道有:

\(ln(1+x)\)

$=\int ~ln(1+x)' $

\(=\int~{1\over 1+x}\)

\(=\int ~ \sum_{i>=0}(-1)^ix^i\)

\(=\sum_{i>=1}{(-1)^{i-1}x^i\over i}\)

\(Ans=exp(\sum_{i=1}^n(ln(1-x^i)-ln(1-x)))[x^k]\)

\(ln(1-x^i)=-\sum_{j>=1}{x^{ij} \over j}\)

所以暴力展开只有调和级数个有用项。

\(ln(1-x)\)同理暴力展开后乘上n即可。

复杂度\(O(n~log~n)\),但是要写MTT,所以跑得巨慢,又难写。

Code:

#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i < B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std; const int mo = 1e9 + 7; ll ksm(ll x, ll y) {
ll s = 1;
for(; y; y /= 2, x = x * x % mo)
if(y & 1) s = s * x % mo;
return s;
} const int N = 1e5 + 5; int n, k, m;
ll fac[N * 2], nf[N * 2];
ll f[450][N];
ll g[N];
void calc(int n) {
fac[0] = 1; fo(i, 1, n) fac[i] = fac[i - 1] * i % mo;
nf[n] = ksm(fac[n], mo - 2); fd(i, n, 1) nf[i - 1] = nf[i] * i % mo;
}
ll C(int n, int m) {
return fac[n] * nf[n - m] % mo * nf[m] % mo;
} int main() {
freopen("b.in", "r", stdin);
freopen("b.out", "w", stdout);
calc(200000);
scanf("%d %d", &n, &k);
m = sqrt(2 * k);
f[0][0] = 1;
fo(i, 1, m) {
fo(j, i, k) {
f[i][j] = f[i][j - i] - f[i - 1][j - i];
if(j >= n + 1) f[i][j] += f[i - 1][j - (n + 1)];
f[i][j] %= mo;
}
}
ll ans = 0;
fo(i, 0, k) {
fo(j, 0, m) g[i] += f[j][i];
g[i] %= mo;
ans += g[i] * fac[n - 1 + (k - i)] % mo * nf[k - i] % mo;
}
ans = (ans % mo * nf[n - 1] % mo + mo) % mo;
pp("%lld\n", ans);
}
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i < B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
#define db double
using namespace std; const int mo = 1e9 + 7; typedef vector<ll> V;
#define si size()
#define pb push_back namespace ntt {
const db pi = acos(-1);
struct P {
db x, y;
P(db _x = 0, db _y = 0) { x = _x, y = _y;}
};
P operator + (P a, P b) { return P(a.x + b.x, a.y + b.y);}
P operator - (P a, P b) { return P(a.x - b.x, a.y - b.y);}
P operator * (P a, P b) { return P(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);}
const int nm = 1 << 18;
int r[nm];
P w[nm], c0[nm], c1[nm], c2[nm], c3[nm]; void dft(P *a, int n) {
ff(i, 0, n) {
r[i] = r[i / 2] / 2 + (i & 1) * (n / 2);
if(i < r[i]) swap(a[i], a[r[i]]);
} P b;
for(int i = 1; i < n; i *= 2) for(int j = 0; j < n; j += 2 * i)
ff(k, 0, i) b = a[i + j + k] * w[i + k], a[i + j + k] = a[j + k] - b, a[j + k] = a[j + k] + b;
}
void rev(P *a, int n) {
reverse(a + 1, a + n);
ff(i, 0, n) a[i].x /= n, a[i].y /= n;
}
P conj(P a) { return P(a.x, -a.y);}
void fft(V &a, V b) {
#define qz(x) ((ll) round(x))
int n = a.si;
// ff(i, 0, n) c0[i] = P(a[i], 0), c1[i] = P(b[i], 0);
// dft(c0, n); dft(c1, n);
// ff(i, 0, n) c0[i] = c0[i] * c1[i];
// dft(c0, n); rev(c0, n);
// ff(i, 0, n) a[i] = qz(c0[i].x) % mo;
// return;
ff(i, 0, n) {
c0[i] = P(a[i] & 32767, a[i] >> 15);
c1[i] = P(b[i] & 32767, b[i] >> 15);
}
dft(c0, n); dft(c1, n);
ff(i, 0, n) {
int j = (n - i) & (n - 1);
P k, d0, d1, d2, d3;
k = conj(c0[j]);
d0 = (k + c0[i]) * P(0.5, 0);
d1 = (k - c0[i]) * P(0, 0.5);
k = conj(c1[j]);
d2 = (k + c1[i]) * P(0.5, 0);
d3 = (k - c1[i]) * P(0, 0.5);
c2[i] = d0 * d2 + d1 * d3 * P(0, 1);
c3[i] = d1 * d2 + d0 * d3;
}
dft(c2, n); dft(c3, n);
rev(c2, n); rev(c3, n);
ff(i, 0, n) {
a[i] = qz(c2[i].x) + (qz(c2[i].y) % mo << 30) + (qz(c3[i].x) % mo << 15);
a[i] %= mo;
}
}
void build() {
for(int i = 1; i < nm; i *= 2) ff(j, 0, i)
ntt :: w[i + j] = P(cos(pi * j / i), sin(pi * j / i));
}
} ll ksm(ll x, ll y) {
ll s = 1;
for(; y; y /= 2, x = x * x % mo)
if(y & 1) s = s * x % mo;
return s;
} V operator + (V a, V b) {
a.resize(max(a.si, b.si));
ff(i, 0, a.si) a[i] = (a[i] + b[i]) % mo;
return a;
}
V operator - (V a, V b) {
a.resize(max(a.si, b.si));
ff(i, 0, a.si) a[i] = (a[i] - b[i] + mo) % mo;
return a;
}
V operator * (V a, int x) {
ff(i, 0, a.si) a[i] = a[i] * x % mo;
return a;
}
V operator * (V a, V b) {
int sa = a.si + b.si - 1, n = 1;
for(; n <= sa; n *= 2);
a.resize(n); b.resize(n);
ntt :: fft(a, b);
a.resize(sa);
return a;
} V qni(V a) {
int n0 = 1; for(; n0 < a.si; n0 *= 2);
V b; b.resize(1); b[0] = ksm(a[0], mo - 2);
for(int n = 2; n <= n0; n *= 2) {
V c = a; c.resize(n);
c = c * b; c.resize(n); c = c * b; c.resize(n);
b = b * 2 - c;
}
b.resize(a.si);
return b;
} V qd(V a) {
ff(i, 1, a.si) a[i - 1] = a[i] * i % mo;
a.resize(a.si - 1);
return a;
}
V jf(V a) {
a.pb(0);
fd(i, a.si - 1, 1) a[i] = a[i - 1] * ksm(i, mo - 2) % mo;
a[0] = 0;
return a;
}
V ln(V a) {
int sa = a.si;
a = jf(qni(a) * qd(a));
a.resize(sa);
return a;
}
V exp(V a) {
int n0 = 1; for(; n0 < a.si; n0 *= 2);
V b; b.resize(1); b[0] = 1;
for(int n = 2; n <= n0; n *= 2) {
V c = b; c.resize(n);
V d = a; d.resize(n);
c = d - ln(c); c[0] ++;
b = b * c; b.resize(n);
}
b.resize(a.si);
return b;
} V a; const int N = 1e5 + 5; int n, k; ll ni[N]; int main() {
freopen("b.in", "r", stdin);
freopen("b.out", "w", stdout);
ntt :: build();
n = 1e5;
fo(i, 1, n) ni[i] = ksm(i, mo - 2);
scanf("%d %d", &n, &k);
a.clear(); a.resize(k + 1);
fo(j, 1, k) a[j] = ni[j] % mo * (n - 1) % mo;
fo(i, 2, n) {
fo(j, 1, k / i) a[i * j] -= ni[j];
}
fo(j, 1, k) a[j] %= mo;
a = exp(a);
pp("%lld\n", (a[k] + mo) % mo);
}

【NOI2019模拟2019.6.27】B (生成函数+整数划分dp|多项式exp)的更多相关文章

  1. [JZOJ6247]【NOI2019模拟2019.6.27】C【计数】

    Description n<=200000 Solution 比赛时没做出这道题真的太弟弟了 首先我们从小到大插入数i,考虑B中有多少个区间的最大值为i 恰好出现的次数不太好计算,我们考虑计算最 ...

  2. 2014北大研究生推免机试(校内)-复杂的整数划分(DP进阶)

    这是一道典型的整数划分题目,适合正在研究动态规划的同学练练手,但是和上一个随笔一样,我是在Coursera中评测通过的,没有找到适合的OJ有这一道题(找到的ACMer拜托告诉一声~),这道题考察得较全 ...

  3. 大概是:整数划分||DP||母函数||递推

    整数划分问题 整数划分是一个经典的问题. Input 每组输入是两个整数n和k.(1 <= n <= 50, 1 <= k <= n) Output 对于每组输入,请输出六行. ...

  4. 51nod 1201 整数划分 dp

    1201 整数划分 基准时间限制:1 秒 空间限制:131072 KB   收藏  关注 将N分为若干个不同整数的和,有多少种不同的划分方式,例如:n = 6,{6} {1,5} {2,4} {1,2 ...

  5. bzoj 3612 [Heoi2014]平衡——整数划分(dp)

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3612 因为力矩的缘故,变成了整数划分. 学习到了整数划分.就是那个图一样的套路.https: ...

  6. bzoj 3612: [Heoi2014]平衡【整数划分dp】

    其实就是-n~n中求选k个不同的数,和为0的方案数 学到了新姿势叫整数划分,具体实现是dp 详见:https://blog.csdn.net/Vmurder/article/details/42551 ...

  7. [JZOJ6244]【NOI2019模拟2019.7.1】islands【计数】【图论】

    Description n<=1e9,M,K<=100 Solution 显然任选m个港口的答案是一样的,乘个组合数即可. 考虑枚举m个港口的度数之和D 可以DP计算 记\(F_{m,D} ...

  8. [JZOJ6244]【NOI2019模拟2019.7.1】Trominoes 【计数】

    Description n,m<=10000 Solution 考虑暴力轮廓线DP,按顺序放骨牌 显然轮廓线长度为N+M 轮廓线也是单调的 1表示向上,0表示向右 N个1,M个0 只能放四种骨牌 ...

  9. [JZOJ6241]【NOI2019模拟2019.6.29】字符串【数据结构】【字符串】

    Description 给出一个长为n的字符串\(S\)和一个长为n的序列\(a\) 定义一个函数\(f(l,r)\)表示子串\(S[l..r]\)的任意两个后缀的最长公共前缀的最大值. 现在有q组询 ...

随机推荐

  1. day04 python列表 元组 range()

    day04 python   一.列表 1.什么是列表     列表是可变的数据类型: 和字符串不同, 做的操作直接改源数据     列表由[]来表示, 每项元素用逗号隔开.列表什么都能装,能装对象的 ...

  2. sqlserver 将店铺表转换成可以用in查询的字符串

    create TABLE #tempshopt ( shopid varchar(max) ) set @aSql = 'insert into #tempshopt(shopid) select s ...

  3. leetcood学习笔记-7

    Python join()方法 join()方法语法: str.join(sequence) 参数 sequence -- 要连接的元素序列. 返回值 返回通过指定字符连接序列中元素后生成的新字符串. ...

  4. Vue学习笔记【19】——Vue中的动画(使用第三方 CSS 动画库)

    导入动画类库:  <link rel="stylesheet" type="text/css" href="./lib/animate.css& ...

  5. apue 第18章 终端I/O

    终端I/O有两种不同的工作模式: (1)规范模式:输入以行单位进行处理,每个读请求也最多返回一行. (2)非规范模式:输入字符不装配成行. 终端设备是由通常位于内核中的终端驱动程序控制的.每个终端设备 ...

  6. 使用pangolin库画出轨迹

    https://github.com/stevenlovegrove/Pangolin cmake_minimum_required(VERSION 2.8) project(chapter3) ) ...

  7. spring AOP (使用AspectJ的xml方式 的aop实现) (7)

    目录 一.定义计算器接口跟实现类 二.定义两个切面,日志切面和验证切面 三.在xml中配置切面 四.测试类 一.定义计算器接口跟实现类 public interface ArithmeticCalcu ...

  8. ASP.NET Core学习——前言

    跌跌撞撞,公司的新项目终于要在这个月月底上线. 新项目使用ASP.NET Core来做,以前没接触过这方面的内容,只能一边学习,一边搞开发. 眼看项目上线在即,工作没那么忙,也不需要天天加班. 回想了 ...

  9. 工具类--MD5Utils

    public class MD5Utils { private static final String[] HEX_DIGITS = { "0", "1", & ...

  10. 1、获取APP 冷/热启动时间

    最近在研究Android APP性能测试.所以发现一些有趣的东西,在这里进行分享.我们先讲第一个内容,如何获取APP冷/热启动时间?为什么要做这个测试,道理其实很简单,如果启动APP特别耗时的话,用户 ...