模拟赛的题

好神仙啊

题面在这里


之前的Solution很蠢 现在已经update....


题意

有$ n$个商品价格均为$ 1$,您有$ m$种面值的货币,面值为$ C_1..C_m$

每种物品你有$ P$的概率选取,然后你需要选出若干货币购买这些物品

购买商品不存在找零,求浪费在找零上的钱的期望对$ 1e9+7$取模

$ n \leq 10^9 \ m \leq 10^2 \ C_iC_j \leq 10^4$


$Solution $

垃圾模数毁我青春

首先考虑$ m=1$怎么做

枚举购买的物品$ a$

概率为$ P(a)=\binom{n}{a}p^a(1-p)^{n-a}$

显然浪费的钱数$ W(a)$可以$ O(1)$计算

然后发现$ W(a)=W(a \bmod C_1)$,即我们只关心选出物品的数量模$ C_1$意义下的每个值的概率

在模意义下建生成函数

即我们要求的多项式为$(px+1-p)^n $长度为$ C_1$的循环卷积结果

注意这里是循环卷积

暴力卷积的时间复杂度是$ O(10^8·\log n)$

一开始看到时限8s就开开心心的去写了,写完一交爆零看到10组数据,然后看到模数就扔题吃饭去了...

使用拆系数$ FFT$/三模数$ NTT$优化这个卷积即可

时间复杂度$ O(10^4·\log 10^4·\log n)$

然后考虑$ m>1$怎么做

其实吃饭的时候嘴巴bb出来了...吃完饭回机房比赛已经结束了...

反正本来也不可能写得出来的...

首先求$ v=\gcd(C_1,C_2..C_m)$,

根据$ NOIP2017$小凯的疑惑,最大的不能被货币表示出的面值$ kv$应该不超过最大的一对$ C$的乘积

这里好像很感性啊..求评论区给出证明QwQ

因此我们对于选出物品数量不超过$ 10^4$的特殊处理

即对于$ i \leq 10^4$求出恰好选了$ i$个物品的概率$ \binom{n}{i}·p^i·(1-p)^{1-i}$

写了个$ MTT$跑的还挺快...

不过常数依然大就是了...


$ my \ code$

#include<ctime>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define block 32768
#define p 1000000007
#define rt register int
#define ll long long
using namespace std;
inline ll read(){
ll x=;char zf=;char ch=getchar();
while(ch!='-'&&!isdigit(ch))ch=getchar();
if(ch=='-')zf=-,ch=getchar();
while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
}
void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
void writeln(const ll y){write(y);putchar('\n');}
int k,m,n,x,y,z,cnt,ans,v;
namespace any_module_NTT{
vector<int>R;
const double PI=acos(-1.0);
struct cp{
double x,y;
cp operator +(const cp s)const{return {x+s.x,y+s.y};}
cp operator -(const cp s)const{return {x-s.x,y-s.y};}
cp operator *(const cp s)const{return {x*s.x-y*s.y,x*s.y+y*s.x};}
}w[][];
void FFT(const int n,vector<cp>&A){
A.resize(n);
for(rt i=;i<n;i++)if(i>R[i])swap(A[i],A[R[i]]);
for(rt i=,s=;i<n;i<<=,s++){
for(rt j=;j<n;j+=i<<){
for(rt k=;k<i;k++){
const register cp x=A[j+k],y=w[s][k]*A[i+j+k];
A[j+k]=x+y,A[i+j+k]=x-y;
}
}
}
}
vector<int>Mul(vector<int>&x,vector<int>&y){
int sz=x.size()+y.size()-,lim=;
while(lim<=sz)lim<<=;R.resize(lim);
vector<cp>AB(lim),CD(lim),AC(lim),BC(lim);
for(rt i=;i<lim;i++)R[i]=(R[i>>]>>)|(i&)*(lim>>);
for(rt i=;i<x.size();i++)AB[i].x=((ll)x[i])&,AB[i].y=((ll)x[i])>>;
for(rt i=;i<y.size();i++)CD[i].x=((ll)y[i])&,CD[i].y=((ll)y[i])>>;
FFT(lim,AB);FFT(lim,CD);
for(rt i=;i<lim;i++){
static cp na,nb,nc,nd;const int pl=(lim-)&(lim-i);
na=AB[i]+(cp){AB[pl].x,-AB[pl].y},nb=AB[i]-(cp){AB[pl].x,-AB[pl].y};
nc=CD[i]+(cp){CD[pl].x,-CD[pl].y},nd=CD[i]-(cp){CD[pl].x,-CD[pl].y};
const cp v1={0.5,},v2={,-0.5};
na=na*v1;nb=nb*v2;nc=nc*v1;nd=nd*v2;
AC[pl]=na*nc+na*nd*(cp){,};
BC[pl]=nb*nc+nb*nd*(cp){,};
}
FFT(lim,AC);FFT(lim,BC);
vector<int>ans(v);
for(rt i=;i<sz;i++){
ll v1=AC[i].x/lim+0.5,v2=AC[i].y/lim+BC[i].x/lim+0.5,v3=BC[i].y/lim+0.5;
(ans[i%v]+=(ll)((v3%p<<)+(v2%p<<)+v1)%p)%=p;
}
return ans;
}
}
using namespace any_module_NTT;
vector<int>a[];
bool vis[];int price[],inv[];
int ksm(int x,int y){
int ans=;
for(rt i=y;i;i>>=,x=1ll*x*x%p)if(i&)ans=1ll*ans*x%p;
return ans;
}
int main(){
for(rt i=;(<<i)<=;i++)
for(rt j=;j<(<<i);j++)w[i][j]={cos(PI*j/(<<i)),sin(PI*j/(<<i))};
for(rt T=read();T;T--){
n=read();m=read();int P=read();v=;
memset(vis,,sizeof(vis));vis[]=;
for(rt i=;i<=m;i++){
x=read();
v=__gcd(v,x);
for(rt j=x;j<=;j++)vis[j]|=vis[j-x];
}
cnt=/v;
for(rt i=;i>=;i--)if(vis[i])price[i]=;else price[i]=price[i+]+;
for(rt i=;i<;i++)a[i].resize(v);
a[][]=;a[][%v]=P;a[][]+=(-P);
for(rt i=;(<<i)<=n;i++)a[i]=Mul(a[i-],a[i-]);
vector<int>ret1(v),ret2(v);bool fla=;
for(rt i=;(<<i)<=n;i++)if(n>>i&)if(!fla)ret1=a[i],fla=;else ret1=Mul(ret1,a[i]);
ll ans=;
for(rt i=;i<v;i++)(ans+=1ll*ret1[i]*(v-i)%p)%=p;
inv[]=inv[]=;
for(rt i=;i<cnt;i++)inv[i]=1ll*inv[p%i]*(p-p/i)%p;
for(rt i=,C=;i<cnt&&i<=n;i++){
const int hf=price[i]-((i%v==)?:(v-i%v));
(ans+=1ll*C%p*ksm(P,i)%p*ksm(-P,n-i)%p*hf%p)%=p;
C=1ll*C*(n-i)%p*inv[i+]%p;
}
writeln((ans+p)%p);
}
return ;
}

「2017 山东三轮集训 Day1」Flair的更多相关文章

  1. 【loj6142】「2017 山东三轮集训 Day6」A 结论题+Lucas定理

    题解: 当奇数 发现答案就是C(n,1)^2+C(n,3)^2+...C(n,n)^2 倒序相加,发现就是C(2n,n) 所以答案就是C(2n,n)/2 当偶数 好像并不会证 打表出来可以得到 2.当 ...

  2. 【loj6145】「2017 山东三轮集训 Day7」Easy 动态点分治+线段树

    题目描述 给你一棵 $n$ 个点的树,边有边权.$m$ 次询问,每次给出 $l$ .$r$ .$x$ ,求 $\text{Min}_{i=l}^r\text{dis}(i,x)$ . $n,m\le ...

  3. loj #6138. 「2017 山东三轮集训 Day4」Right

    题目: 题解: 暴力一波 \(SG\) 函数可以发现这么一个规律: \(p\) 为奇数的时候 : \(SG(n) = n \% 2\) \(p\) 为偶数的时候 : \(SG(n) = n \% (p ...

  4. loj #6136. 「2017 山东三轮集训 Day4」Left

    题目: 题解: 我们可以发现所有的交换器都是一个位置连接着下一层左侧的排序网络,另一个位置连着另一侧的排序网络. 而下一层是由两个更低阶的排序网络构成的. 两个网络互不干扰.所以我们可以通过第一行和最 ...

  5. 「2017 山东三轮集训 Day7」Easy

    一棵带边权的树,多次询问 $x$ 到编号为 $[l,r]$ 的点最短距离是多少 $n \leq 100000$ sol: 动态点分治,每层重心维护到所有点的距离 查询的时候在管辖这个点的 log 层线 ...

  6. #6145. 「2017 山东三轮集训 Day7」Easy 动态点分治

    \(\color{#0066ff}{题目描述}\) JOHNKRAM 最近在参加 C_SUNSHINE 举办的聚会. C 国一共有 n 座城市,这些城市由 n−1 条无向道路连接.任意两座城市之间有且 ...

  7. Loj #6142. 「2017 山东三轮集训 Day6」A

    link: https://loj.ac/problem/6142 推完一波式子之后发现求的是:ΣC(N,i)^2, 其中i是偶数. 然后就可以卢卡斯乱搞了,分奇偶和之前的答案合并就好了233. #i ...

  8. LOJ #6145. 「2017 山东三轮集训 Day7」Easy 点分树+线段树

    这个就比较简单了~ Code: #include <cstdio> #include <algorithm> #define N 100004 #define inf 1000 ...

  9. 「2017 山东三轮集训 Day7 解题报告

    「2017 山东三轮集训 Day7」Easy 练习一下动态点分 每个点开一个线段树维护子树到它的距离 然后随便查询一下就可以了 注意线段树开大点... Code: #include <cstdi ...

随机推荐

  1. linux 下 命令行中运行 selenium chrome 问题

    1.chrome 现在不允许使用root运行了. 2.无界面 chromedriver 调用chrome 会出错. <另外一定要匹配 chromedriver和chrome 的版本. 要不会出各 ...

  2. MAX

    Max的用法1(Min类似) Matlab中max函数在矩阵中求函数大小的实例如下: C = max(A)返回一个数组各不同维中的最大元素.如果A是一个向量,max(A)返回A中的最大元素.如果A是一 ...

  3. Redis入门---字符串类型

    阅读目录 1.keys * 命令 2.判断一个键是否存在(exists key) 3.删除键 4.获取键值的数据类型 5 递增数字(incr) 6.增加指定的整数 (INCRBY) 7.减少指定的整数 ...

  4. 怎么在Vue的某个组件中根据组件tag标签名获取到对应的VueComponent实例呢

    1.以前玩omi框架的时候,有Omi.get方法来获取实例, ...好久没玩了,忘了.反正很喜欢该方法.2.如今想在vue里面怎么能够快速获取到对应组件标签名的的实例呢?3.文档也看过,似乎脑海中没啥 ...

  5. mysql之优化(2)

    1.选取最适用的字段属性MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽可 ...

  6. Windows 虚拟机 忘记密码的处理

    说明 经过验证 没法用这种方式处理 之前的系统够可以 2016的方法 稍后在写一个. 1. 修改虚拟机的配置界面: 2. 增加windows的安装盘 作为启动盘 3 bios 里面设置CD启动 比较简 ...

  7. MyBatis的接口式编程Demo

    很久没细看过MyBatis了,时间一长就容易忘记. 下面是一个接口式编程的例子. 这里的例子一共分为4步: 1 首先要有一个namespace为接口的全类名的映射文件,该例中是 IMyUser.xml ...

  8. Java 面向对象的基本特征

    前言:  在刚开始接触Java的时候,那时候面对Java面向对象的几大特征一直理解的不是很理解,借着空闲时间在这里整理一下,同时在加深一下印象. 一.封装: Java面向对象的特征之封装,所谓的封装就 ...

  9. python 基本数据类型以及运算符操作

    一.基本数据类型 为何要区分类型? 数据类型的值是变量值得类型,变量值之所以区分类型,是因为变量的值 用来记录事物的状态,而事物的状态有不同的种类,对应着,也必须用不 用类型去区分它们. 1.数字类型 ...

  10. ThreadPoolExecutor 中的 shutdown() 、awaitTermination() 、 shutdownNow() 的用法

    shutdown和awaitTermination为接口ExecutorService定义的两个方法,一般情况配合使用来关闭线程池. 方法简介shutdown方法:将线程池状态置为SHUTDOWN.平 ...