【SDOI2017】遗忘的集合
好神仙啊,我还真的以为这是个构造题,结果是有唯一解的。
设答案为多项式\(a,a_i\in\{0,1\}\)。
则:
\]
两边取对数:
ln(f(x))&=\sum a_i ln(\frac{1}{1-x^i})
\\&=-\sum a_iln(1-x^i)
\end{align}
\]
我们在对\(ln(x)\)在\(x=1\)处进行泰勒展开。
由:
ln(x)&=\sum_{i=0}^{\infty}\frac{ln^{[i]}(x_0)}{i!}(x-x_0)^i\\
&=\sum_{i=1}^{\infty}(-1)^{i-1}\frac{1}{i}(x-1)^i
\end{align}
\]
得到:
\]
所以:
ln(f(x))&=-\sum a_i \sum_{j=1}^{\infty}(-1)\frac{x^{ij}}{j}
\\&=\sum_{i=1}^n x^i\sum_{j|i}a_j\frac{j}{i}
\\&=\sum_{i=1}^n\frac{x^i}{i}\sum_{j|i}a_jj
\end{align}
\]
求出\(ln(f(x))\)后就可以用\(nlogn\)的复杂度求出\(a\)了。
因为是任意模数,所以要写\(MTT\)。
推导很自然,思路很巧妙啊。关键是要想到列出关于答案数组\(a\)的等式再去将\(a\)解出来。
代码:
#include<bits/stdc++.h>
using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
typedef long long ll;
const int N=(1<<19);
const ll sqr=1<<15;
ll mod;
ll a[N<<2];
struct Com {
double r,v;
Com() {r=0,v=0;}
Com(double a,double b) {r=a,v=b;}
};
Com operator *(const Com &a,const Com &b) {return Com(a.r*b.r-a.v*b.v,a.r*b.v+a.v*b.r);}
Com operator /(const Com &a,const double &y) {return Com(a.r/y,a.v/y);}
Com operator +(const Com &a,const Com &b) {return Com(a.r+b.r,a.v+b.v);}
Com operator -(const Com &a,const Com &b) {return Com(a.r-b.r,a.v-b.v);}
Com w[N<<2];
const double pi=acos(-1);
void FFT(Com *a,int d,int flag) {
static int rev[N<<2];
int n=1<<d;
for(int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<d-1);
for(int i=0;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int i=0;i<n;i++) w[i]=Com(cos(2*flag*i*pi/n),sin(2*flag*i*pi/n));
for(int s=1;s<=d;s++) {
int len=1<<s,mid=len>>1;
for(int i=0;i<n;i+=len) {
for(int j=0;j<mid;j++) {
Com u=a[i+j],v=a[i+j+mid]*w[n/len*j];
a[i+j]=u+v;
a[i+j+mid]=u-v;
}
}
}
if(flag==-1) for(int i=0;i<n;i++) a[i]=a[i]/n;
}
Com f1[N<<2],f2[N<<2],g1[N<<2],g2[N<<2];
Com A[N<<2],B[N<<2],C[N<<2],D[N<<2];
void mul(ll *f,ll *g,int d,ll *ans) {
int n=1<<d;
for(int i=0;i<n;i++) {
f1[i]=Com(f[i]/sqr,0),f2[i]=Com(f[i]%sqr,0);
g1[i]=Com(g[i]/sqr,0),g2[i]=Com(g[i]%sqr,0);
}
for(int i=0;i<n<<1;i++) ans[i]=0;
for(int i=n;i<n<<1;i++) f1[i]=f2[i]=g1[i]=g2[i]=Com(0,0);
FFT(f1,d+1,1),FFT(f2,d+1,1),FFT(g1,d+1,1),FFT(g2,d+1,1);
for(int i=0;i<n<<1;i++) {
A[i]=f1[i]*g1[i];
B[i]=f1[i]*g2[i];
C[i]=f2[i]*g1[i];
D[i]=f2[i]*g2[i];
}
FFT(A,d+1,-1),FFT(B,d+1,-1),FFT(C,d+1,-1),FFT(D,d+1,-1);
for(int i=0;i<n;i++) ans[i]=(ll(A[i].r+0.5)*sqr%mod*sqr%mod+ll(B[i].r+0.5)*sqr+ll(C[i].r+0.5)*sqr+ll(D[i].r+0.5))%mod;
for(int i=n;i<n<<1;i++) ans[i]=0;
}
ll ksm(ll t,ll x) {
ll ans=1;
for(;x;x>>=1,t=t*t%mod)
if(x&1) ans=ans*t%mod;
return ans;
}
int n,m;
ll tem[N<<2];
void inverse(ll *a,ll *f,int len) {
if(len==1) {return f[0]=ksm(a[0],mod-2),void();}
int d=ceil(log2(len));
inverse(a,f,len>>1);
mul(a,f,d,tem);
mul(tem,f,d,tem);
for(int i=0;i<len;i++) f[i]=(2*f[i]-tem[i]+mod)%mod;
}
ll inv[N<<2];
void Ln(ll *a,ll *ans,int len) {
for(int i=0;i<len-1;i++) ans[i]=a[i+1]*(i+1)%mod;
int d=ceil(log2(len));
inverse(a,inv,len);
ans[len-1]=0;
mul(ans,inv,d,ans);
for(int i=len-1;i;i--) ans[i]=ans[i-1]*ksm(i,mod-2)%mod;
ans[0]=0;
}
ll f[N<<2];
int main() {
n=Get(),mod=Get();
for(int i=1;i<=n;i++) a[i]=Get();
a[0]=1;
int d=ceil(log2(n+1));
Ln(a,f,1<<d);
for(int i=1;i<=n;i++) f[i]=f[i]*i%mod;
int tot=0;
for(int i=1;i<=n;i++) {
for(int j=i+i;j<=n;j+=i) {
f[j]=(f[j]-f[i]+mod)%mod;
}
if(f[i]) tot++;
}
cout<<tot<<"\n";
for(int i=1;i<=n;i++) if(f[i]) cout<<i<<" ";
return 0;
}
【SDOI2017】遗忘的集合的更多相关文章
- [SDOI2017]遗忘的集合
[SDOI2017]遗忘的集合 综合了很多套路的题 一看就是完全背包 生成函数! 转化为连乘积形式 Pi....=F 求Ln! 降次才可以解方程 发现方程是: f[i]=∑t|i : bool(t)* ...
- [LOJ2271] [SDOI2017] 遗忘的集合
题目链接 LOJ:https://loj.ac/problem/2271 洛谷:https://www.luogu.org/problemnew/show/P3784 BZOJ太伤身体死活卡不过还是算 ...
- 洛谷P3784 [SDOI2017]遗忘的集合(生成函数)
题面 传送门 题解 生成函数这厮到底还有什么是办不到的-- 首先对于一个数\(i\),如果存在的话可以取无限多次,那么它的生成函数为\[\sum_{j=0}^{\infty}x^{ij}={1\ove ...
- [题解] LuoguP3784 [SDOI2017]遗忘的集合
要mtt的题都是...... 多补了几项就被卡了一整页......果然还是太菜了...... 不说了......来看100分的做法吧...... 如果做过付公主的背包,前面几步应该不难想,所以我们再来 ...
- [BZOJ4913][SDOI2017]遗忘的集合
题解: 首先先弄出$f(x)$的生成函数$$f(x)=\prod_{i=1}^{n} {{(\frac{1}{1-x^i})}}^{a[i]}$$因为$f(x)$已知,我们考虑利用这个式子取推出$a[ ...
- P3784 [SDOI2017]遗忘的集合
非常神仙的一道题! 题意:给出某n个数字跑完全背包m容量的dp数组,求满足要求的字典序最小的n个元素,不知道n是多少. 首先考虑付公主的背包这个题. 对dp数组求一个ln,设它为F. 已知 e^(G1 ...
- 洛谷 3784(bzoj 4913) [SDOI2017]遗忘的集合——多项式求ln+MTT
题目:https://www.luogu.org/problemnew/show/P3784 https://www.lydsy.com/JudgeOnline/problem.php?id=4913 ...
- SDOI2017遗忘的集合
题面链接 咕咕咕 题外话 为了这道题我敲了\(MTT\).多项式求逆.多项式\(ln\)等模板,搞了将近一天. sol 最近懒得写题解啊,随便搞搞吧. 看到这个就是生成函数套上去. \[F(x)=\p ...
- BZOJ 4913 [Sdoi2017] 遗忘的集合
骂了隔壁的 BZOJ垃圾评测机 我他妈卡了两页的常数了 我们机房的电脑跑的都比BZOJ快
随机推荐
- SQL语句NOT IN优化之换用NOT EXISTS
NOT IN查询示例(示例背景描述:根据条件查询Questions表得到的数据基本在PostedData表中不存在,为完全保证查询结果在PostedData表中不存在,使用NOT IN): SET S ...
- mysqlslap 压力测试使用总结
今天从运维同事那听说了mysql压力测试工具mysqlslap.经了解其实mysql自带就有一个叫mysqlslap的压力测试工具,还是模拟的不错的.下面举例说说.mysqlslap是从5.1.4版开 ...
- Spring Boot从入门到精通之:一、Spring Boot简介及快速入门
Spring Boot Spring Boot 简介 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来 ...
- SSM 设置静态资源处理
使用weblogic的虚拟路径virtual-directory-mapping 在页面上展示文件服务器上的图片 <weblogic-web-app> ......省略其他部分 <c ...
- Dev、GridControl的模糊查询
/// <summary> /// 设置girid为每一列都模糊搜索 /// </summary> /// <param name="gdv"> ...
- angular 分页插件的使用
html: <pagination total-items="totalItems" ng-model="currentPage" items-per-p ...
- SAP MM MM17里不能修改物料主数据'Purchasing Value Key'字段值?
SAP MM MM17里不能修改物料主数据'Purchasing Value Key'字段值? 记得在D项目上线之前数据导入系统之后,业务提出一些物料采购视图里的’Purchasing value k ...
- Spring学习之旅(七)基于XML配置与基于AspectJ注解配置的AOP编程比较
本篇博文用一个稍复杂点的案例来对比一下基于XML配置与基于AspectJ注解配置的AOP编程的不同. 相关引入包等Spring AOP编程准备,请参考小编的其他博文,这里不再赘述. 案例要求: 写一 ...
- C# 简单实现直线方程,抛物线方程
本例子是简单的在WinForm程序中实现在坐标系中绘制直线方程,抛物线方程,点.重新学习解析几何方面的知识.仅供学习分享使用,如有不足之处,还请指正. 涉及知识点: 直线方程的表达方式:一般表达式Ax ...
- Android Studio多渠道打包(二)
虽然多渠道打包的方式有很多种,那么今天我要说的通过工具的形式进行多渠道打包 首先,打开Android studio,找到顶部Build,点开 选择红色部分,里面的编辑框可以帮助我们更快的熟悉Gradl ...