loj6077
题解:
网上的做法好像都是容斥
那就先说一下容斥
首先问题等价于求下面这个式子的方案数
$$\sum_{i=1}^{n} ai (0<ai<i) =k$$
直接$dp$复杂度是$nk$的,无法接受
我们考虑容斥
答案=所有-至少1个不满足+至少2个不满足-....
而不满足等价于$ai>=i$ 那么我们只需要令$b[i]=a[i]-i$就可以与其他等价了
实际上这样子看上去这个容斥并没有用处
因为要$dp$出容斥系数看上去至少是$O(n^2)$
现在我们需要算出,用i个不相同的数相加=k的方案数
我们注意一件事情,i的取值只有$\sqrt{k}$,所以如果状态设计得好,是可以的
要求数不同有一个经典套路就是 把操作转化成
1.给当前数组内全体数+1
2.给当前数组内全体数+1再在末尾放一个1
于是$f[i][j]$表示数组内有i个数,和为j的方案数 $$f[i][j]=f[i-1][j-i]+f[i][j-i]$$复杂度$n\sqrt{n}$
然后你写一下,肯定会发现出问题了(我没写这种做法但下面这种的时候遇到了同样的问题)
因为这么做可能有数>n了
怎么保证没有数>n呢,我们只需要令每个时刻的$f[i][j]$都是<=n的
那么出现大于n的只可能是n+1,$f[i][j]-=f[i-1][j-n-1]$就可以了
还是比较难想的。。
这题还有个做法是生成函数,在思维上就简单很多
$$f(x)=\frac{\prod_{i=1}^{n} (1-x^i)}{(1-x)^n}$$
然后要求这个东西,暴力是n^2logn的
然后乘法比较显然的是两边取ln,得到
$$ln(f(x))=\sum_{i=1}^{n} {ln(1-x^i)} - n*ln(1-x)$$
这样子我们发现要解决的就是$ln(1-x^i)$
这个东西就两项但我们要用$nlogn$的多项式求逆是不是太浪费了
于是打表找规律,可以发现(不过要是不知道结论考场谁有时间去打个多项式求ln找规律啊。。)
$ln(1-x)=\frac{1}{1}x+\frac{1}{2}x^2+\frac{1}{3}x^3+...$
$ln(1-x^2)=\frac{1}{1}x^2+\frac{1}{2}x^4+\frac{1}{3}x^6+...$
下面的规律同理
于是我们可以利用筛法在$nlogn$时间内求出
当然由于$$f(x)=\sum {d|x} {}{ \ \ \ g1(d)g2(\frac{x}{d}) }$$ 其中$g1(i)=\frac{1}{i},g2(i)=1$
因为$g1(i),g2(i)$是完全积性函数(只要是积性就可以了),所以他们的卷积也是积性函数
所以可以用线性筛做到$O(n)$ 我们类似于做约数和再维护一个h(i)表示不包括i的最小素因子的g1的和
于是就是多项式exp模板题了
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for(int i=h;i<=t;i++)
#define dep(i,t,h) for(int i=t;i>=h;i--)
#define ll long long
#define me(x) memset(x,0,sizeof(x))
#define mep(x,y) memcpy(x,y,sizeof(y))
#define mid (t<=0?(h+t-1)/2:(h+t)/2)
namespace IO{
char ss[<<],*A=ss,*B=ss;
IL char gc()
{
return A==B&&(B=(A=ss)+fread(ss,,<<,stdin),A==B)?EOF:*A++;
}
template<class T> void read(T &x)
{
rint f=,c; while (c=gc(),c<||c>) if (c=='-') f=-; x=(c^);
while (c=gc(),c>&&c<) x=(x<<)+(x<<)+(c^); x*=f;
}
char sr[<<],z[]; ll Z,C1=-;
template<class T>void wer(T x)
{
if (x<) sr[++C1]='-',x=-x;
while (z[++Z]=x%+,x/=);
while (sr[++C1]=z[Z],--Z);
}
IL void wer1()
{
sr[++C1]=' ';
}
IL void wer2()
{
sr[++C1]='\n';
}
template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;}
template<class T>IL void mina(T &x,T y) {if (x>y) x=y;}
template<class T>IL T MAX(T x,T y){return x>y?x:y;}
template<class T>IL T MIN(T x,T y){return x<y?x:y;}
};
using namespace IO;
const double ee=1.00000000000000;
const double pi=acos(-1.0);
const int N=4e5+;
const int mo=1e9+;
int r[N],n,m,l,inv[N],n1[N],n2[N];
struct cp{
double a,b;
IL cp operator +(const cp &o) const
{
return (cp){a+o.a,b+o.b};
}
IL cp operator -(const cp &o) const
{
return (cp){a-o.a,b-o.b};
}
IL cp operator *(register const cp &o) const
{
return (cp){a*o.a-b*o.b,o.a*b+o.b*a};
}
}a[N],b[N],c[N],d[N];
IL int fsp(int x,int y)
{
ll now=;
while (y)
{
if (y&) now=now*x%mo;
x=1ll*x*x%mo;
y>>=;
}
return now;
}
IL void clear()
{
for (int i=;i<=n;i++) a[i].a=a[i].b=b[i].a=b[i].b=c[i].a=c[i].b=d[i].a=d[i].b=;
}
cp *w[N],tmp[N*];
int p;
IL void init()
{
cp *now=tmp;
for (int i=;i<=p;i<<=)
{
w[i]=now;
for (int j=;j<i;j++) w[i][j]=(cp){cos(pi*j/i),sin(pi*j/i)};
now+=i;
}
}
IL void fft_init()
{
l=; for (n=;n<=m;n<<=) l++;
for (int i=;i<n;i++) r[i]=(r[i/]/)|((i&)<<(l-));
}
void fft(cp *a,int o)
{
for (int i=;i<n;i++) if (i>r[i]) swap(a[i],a[r[i]]);
for (int i=;i<n;i<<=)
for (int j=;j<n;j+=(i*))
{
cp *x1=a+j,*x2=a+i+j,*W=w[i];
for (int k=;k<i;k++,x1++,x2++,W++)
{
cp x=*x1,y=(cp){(*W).a,(*W).b*o}*(*x2);
*x1=x+y,*x2=x-y;
}
}
if (o==-) for(int i=;i<n;i++) a[i].a/=n;
}
IL void getcj(int *A,int *B,int len)
{
rep(i,,len)
{
A[i]=(A[i]+mo)%mo,B[i]=(B[i]+mo)%mo;
}
for (int i=;i<len;i++)
{
a[i]=(cp){A[i]&,A[i]>>};
b[i]=(cp){B[i]&,B[i]>>};
}
m=len*; fft_init();
fft(a,); fft(b,);
for (int i=;i<n;i++)
{
int j=(n-)&(n-i);
c[j]=(cp){0.5*(a[i].a+a[j].a),0.5*(a[i].b-a[j].b)}*b[i];
d[j]=(cp){0.5*(a[i].b+a[j].b),0.5*(a[j].a-a[i].a)}*b[i];
}
fft(c,); fft(d,);
double inv=ee/n;
rep(i,,n) c[i].a*=inv,c[i].b*=inv;
rep(i,,n) d[i].a*=inv,d[i].b*=inv;
rep(i,,len)
{
ll a1=c[i].a+0.5,a2=c[i].b+0.5;
ll a3=d[i].a+0.5,a4=d[i].b+0.5;
B[i]=(a1+((a2+a3)%mo<<)+((a4%mo)<<))%mo;
}
clear();
}
void getinv(int *A,int *B,int len)
{
if (len==) { B[]=fsp(A[],mo-); return;};
getinv(A,B,(len+)/);
int C[N]={};
rep(i,,len-) C[i]=A[i];
getcj(B,C,len);
getcj(B,C,len);
for (int i=;i<len;i++) B[i]=((2ll*B[i]-C[i])%mo+mo)%mo;
}
IL void getDao(int *a,int *b,int len)
{
for (int i=;i<len;i++) b[i-]=1ll*i*a[i]%mo;
b[len-]=;
}
IL void getjf(int *a,int *b,int len)
{
for (int i=;i<len;i++) b[i+]=1ll*a[i]*inv[i+]%mo;
b[]=;
}
IL void getln(int *A,int *B,int len)
{
int C[N]={},D[N]={};
getDao(A,C,len);
getinv(A,D,len);
getcj(C,D,len);
getjf(D,B,len);
}
IL void getexp(int *A,int *B,int len)
{
if (len==) {B[]=; return;}
getexp(A,B,(len+)>>);
int C[N]={};
getln(B,C,len);
for(int i=;i<len;i++) C[i]=(-C[i]+A[i])%mo;
C[]=(C[]+)%mo;
getcj(C,B,len);
}
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
inv[]=;
rep(i,,1e5+) inv[i]=(1ll*inv[mo%i]*(mo-(mo/i)))%mo;
int n,k;
read(n); read(k); k++;
n1[]=; n1[]=-;
p=k<<;
init();
getln(n1,n2,k);
rep(i,,k) n1[i]=-1ll*n*n2[i]%mo;
rep(i,,n)
{
for(int j=;j*i<=k;j++)
(n1[i*j]-=inv[j])%=mo;
}
me(n2);
getexp(n1,n2,k);
cout<<(n2[k-]+mo)%mo<<endl;
return ;
}
loj6077的更多相关文章
- 【LOJ6077】「2017 山东一轮集训 Day7」逆序对 生成函数+组合数+DP
[LOJ6077]「2017 山东一轮集训 Day7」逆序对 题目描述 给定 n,k ,请求出长度为 n的逆序对数恰好为 k 的排列的个数.答案对 109+7 取模. 对于一个长度为 n 的排列 p ...
- loj6077. 「2017 山东一轮集训 Day7」逆序对
题目描述: loj 题解: 容斥+生成函数. 考虑加入的第$i$个元素对结果的贡献是$[0,i-1]$,我们可以列出生成函数. 长这样:$(1)*(1+x)*(1+x+x^2)*--*(1+x+x^2 ...
- LOJ6077「2017 山东一轮集训 Day7」逆序对 (生成函数+多项式exp?朴素DP!)
题面 给定 n , k n,k n,k ,求长度为 n n n 逆序对个数为 k k k 的排列个数,对 1 e 9 + 7 \rm1e9+7 1e9+7 取模. 1 ≤ n , k ≤ 100 ...
- 8月清北学堂培训 Day3
今天是赵和旭老师的讲授~ 状态压缩 dp 状态压缩是设计 dp 状态的一种方式. 当普通的 dp 状态维数很多(或者说维数与输入数据有关),但每一维总量很少时,可以将多维状态压缩为一维来记录. 这种题 ...
- DP&图论 DAY 3 上午
DP&图论 DAY 3 上午 状态压缩dp >状态压缩dp ◦状态压缩是设计dp状态的一种方式.◦当普通的dp状态维数很多(或者说维数与输入数据有关),但每一维总量很少是,可以将多维 ...
随机推荐
- github 管理代码: code.Aliyun
阿里云代码管理,,cao,搞了半天,配置百度就可以了,我只想说代码控制可以用github桌面版管理
- pymysql模块
一.pymysql模块 1.说明: 想在python代码中连接上mysql数据库,就需要使用pymysql模块, pymysql是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,在 ...
- 深入理解AMQP协议
深入理解AMQP协议 2018年10月22日 12:32:16 一剑何风情 阅读数:1941 文章目录 一.AMQP 是什么 二.AMQP模型 工作过程 深入理解 三.Exchange交换机 默认 ...
- P3389 【模板】高斯消元法
高斯消元求解n元一次线性方程组的板子题: 先举个栗子: • 2x + y - z = 8-----------① •-3x - y + 2z = -11---------② •-2x + y + ...
- Android学习第九天
为什么需要内容提供者 a) 如何创建数据库 b) 文件权限 c) Chmod linux修改权限 内容提供者原理 a) 内容提供者把数据进行封 ...
- Hdoj 1850.Being a Good Boy in Spring Festival 题解
Problem Description 一年在外 父母时刻牵挂 春节回家 你能做几天好孩子吗 寒假里尝试做做下面的事情吧 陪妈妈逛一次菜场 悄悄给爸爸买个小礼物 主动地 强烈地 要求洗一次碗 某一天早 ...
- 【BZOJ5498】[十二省联考2019]皮配(动态规划)
[BZOJ5498][十二省联考2019]皮配(动态规划) 题面 BZOJ 洛谷 题解 先考虑暴力\(dp\),设\(f[i][j][k]\)表示前\(i\)所学校,有\(j\)人在某个阵营,有\(k ...
- 【机器学习】BP & softmax求导
目录 一.BP原理及求导 二.softmax及求导 一.BP 1.为什么沿梯度方向是上升最快方向 根据泰勒公式对f(x)在x0处展开,得到f(x) ~ f(x0) + f'(x0)(x-x0) ...
- A Graph Partitioning Game Theoretical Approach for the VNF Service Chaining Problem
文章名称:A Graph Partitioning Game Theoretical Approach for the VNF Service Chaining Problem 发表时间:2017 期 ...
- Pandas系列(七)-计算工具介绍
内容目录 1. 统计函数 2. 窗口函数 3. 加深加强 数据准备 # 导入相关库 import numpy as np import pandas as pd #Pandas 中包含了非常丰富的计算 ...