其实是CF868G的加强版

把概率变成任意了(好吧也没加强什么东西)做法还是一样。

注意,按理说应该要特判p=1p=1p=1的情况,然而没有卡。。。

题解:

首先确定策略,我们的策略显然是每次贪心找到当前已经被访问次数最少的洞穴。

那么每次就是访问(i−1)∗k+1→i∗k(i-1)*k+1\rightarrow i*k(i−1)∗k+1→i∗k在%n\%n%n意义下的所有洞穴。

设eie_iei​表示宝藏在iii号洞穴时的期望探测步数,则答案为∑ein\frac{\sum e_i}{n}n∑ei​​

那么p=1p=1p=1的时候的答案为(设t=⌊n−1k⌋t=\lfloor\frac{n-1}{k}\rfloort=⌊kn−1​⌋):
∑i=1n⌊i−1k+1⌋=n+k⋅t⋅(t−1)/2+(n−t⋅k)⋅t\sum_{i=1}^{n}\lfloor\frac{i-1}{k}+1\rfloor=n+k\cdot t\cdot (t-1)/2+(n-t\cdot k)\cdot t i=1∑n​⌊ki−1​+1⌋=n+k⋅t⋅(t−1)/2+(n−t⋅k)⋅t

然后乘上nnn的逆元就行了

其实eie_iei​有表达式,我们考虑令前j−1j-1j−1次访问这个山洞都没有找到宝藏,且在第jjj次找到:

ei=∑j=1∞(1−p)j−1p⌊i−1+n⋅(j−1)k+1⌋e_i=\sum_{j=1}^\infty(1-p)^{j-1}p\lfloor\frac{i-1+n\cdot (j-1)}{k}+1\rfloor ei​=j=1∑∞​(1−p)j−1p⌊ki−1+n⋅(j−1)​+1⌋

这个并不能用类欧几里得做,因为上标是∞\infty∞

直接对于i=1,⋯,ni=1,\cdots ,ni=1,⋯,n求和也很麻烦。

但是注意到这给了我们eie_iei​之间的递推关系。

对于k<i≤nk< i\leq nk<i≤n,ei=ei−k+1e_i=e_{i-k}+1ei​=ei−k​+1

对于1≤i≤k1\leq i\leq k1≤i≤k,ei=(1−p)ei−k+n+1e_i=(1-p)e_{i-k+n}+1ei​=(1−p)ei−k+n​+1

我们发现,%gcd(n,k)\%gcd(n,k)%gcd(n,k)后相同的位置形成了一个环,并且每个环上的方程是一样的,也就是说,我们把n,kn,kn,k同时除掉gcd答案不会改变。

于是我们可以利用一次函数复合得到关于e1e_1e1​的方程,然后顺着解下去,复杂度O(n)O(n)O(n)。

考虑一个更加优秀的做法,我们先把eie_iei​变成关于iii的函数f(i)f(i)f(i)(为了写起来方便)。

显然fff在i=1,2⋯,ni=1,2\cdots ,ni=1,2⋯,n的取值形成的数列就是eie_iei​。

现在给定n,kn,kn,k,并且在i=1,2,⋯ni=1,2,\cdots ni=1,2,⋯n中,以kkk为分界线函数值有一次函数复合关系。

则考虑构造一次函数A(x),B(x)A(x),B(x)A(x),B(x),使得f(i)=B(f(i−k+n))=A(f(i−k))f(i)=B(f(i-k+n))=A(f(i-k))f(i)=B(f(i−k+n))=A(f(i−k))

然后考虑迭代,显然我们需要对于前后分开考虑,设置一次函数S1,S2S1,S2S1,S2,令我们当前需要求的是:

∑i=1kS1(f(i))+∑i=k+1nS2(f(i))\sum_{i=1}^kS1(f(i))+\sum_{i=k+1}^nS2(f(i))i=1∑k​S1(f(i))+i=k+1∑n​S2(f(i))

考虑迭代,设n′=k,k′=n%kn'=k,k'=n\%kn′=k,k′=n%k,那么我们需要考虑构造A′,B′,S1′,S2′A',B',S1',S2'A′,B′,S1′,S2′使得迭代出来的形式和上面相同,及需要找到合法的这四个一次函数,使得:

∑i=1kS1(f(i))+∑i=k+1nS2(f(i))=∑i=1k′S1′(f(i))+∑i=k′+1n′S2′(f(i))f(i)=B′(f(i−k′+n′))=A′(f(i−k′))\sum_{i=1}^kS1(f(i))+\sum_{i=k+1}^nS2(f(i))=\sum_{i=1}^{k'}S1'(f(i))+\sum_{i=k'+1}^{n'}S2'(f(i))\\ f(i)=B'(f(i-k'+n'))=A'(f(i-k')) i=1∑k​S1(f(i))+i=k+1∑n​S2(f(i))=i=1∑k′​S1′(f(i))+i=k′+1∑n′​S2′(f(i))f(i)=B′(f(i−k′+n′))=A′(f(i−k′))

接下来声明两个个记号:

对于函数FFF,以下如无特殊说明F−1F^{-1}F−1表示FFF的复合逆,即F(F−1(x))=F−1(F(x))=I(x)F(F^{-1}(x))=F^{-1}(F(x))=I(x)F(F−1(x))=F−1(F(x))=I(x),其中III表示复合操作的单位元,即I(x)=xI(x)=xI(x)=x

对于函数AAA,令A0=I,A1=A,Ai=A(Ai−1)A^0=I,A^1=A,A^i=A(A^{i-1})A0=I,A1=A,Ai=A(Ai−1),即自我复合iii次。

很显然地,我们可以通过辗转相除直接得到A′A'A′和B′B'B′的表达式:
A′=A−⌊nk−1⌋(B−1)B′=A−⌊nk⌋(B−1)A'=A^{-\lfloor\frac{n}{k}-1\rfloor}(B^{-1})\\ B'=A^{-\lfloor\frac{n}{k}\rfloor}(B^{-1}) A′=A−⌊kn​−1⌋(B−1)B′=A−⌊kn​⌋(B−1)

同样地,考虑i=n′+1,n′+2⋯,ni=n'+1,n'+2\cdots,ni=n′+1,n′+2⋯,n最终落在[1,n′][1,n'][1,n′]中的哪个位置上,我们同样可以得到S1′=S1+∑i=1⌊nk⌋S2(Ai)S2′=S1+∑i=1⌊nk−1⌋S2(Ai)S1'=S1+\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}S2(A^i)\\ S2'=S1+\sum_{i=1}^{\lfloor\frac{n}{k}-1\rfloor}S2(A^i) S1′=S1+i=1∑⌊kn​⌋​S2(Ai)S2′=S1+i=1∑⌊kn​−1⌋​S2(Ai)

发现逆元,复合的iii次幂都很好计算。

但是这个东西相当扯淡:∑i=1tS2(Ai)\sum_{i=1}^tS2(A^i)i=1∑t​S2(Ai)

直接计算是没有办法搞的,但是我们可以算这个东西:
S2(∑i=1tAi)S2(\sum_{i=1}^tA^i)S2(i=1∑t​Ai)

但是实际上这俩不是同一个东西,我们虽然明确了这里用到的所有函数,除了fff全部都是一次函数,但是我们仔细考虑一下,上面两个东西在算S2S2S2的常数项被算了几次的时候就出事了,下面那个只算了一次,上面那个算了ttt次,但是其他地方都work得很好。

所以对于所有的SSS,我们需要把常数项单独提取出来算,才能保证答案正确。

递归边界k=0k=0k=0,这时候f(i)=A(f(i)),f(i)=A(f(i)),f(i)=A(f(i)),大力计算即可。


代码:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs constusing std::cerr;
using std::cout;cs int mod=1e9+7;
inline int add(int a,int b){a+=b-mod;return a+(a>>31&mod);}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline int power(int a,int b,int res=1){for(;b;b>>=1,a=mul(a,a))(b&1)&&(res=mul(res,a));return res;
}
inline void Inc(int &a,int b){a+=b-mod;a+=a>>31&mod;}
inline void Dec(int &a,int b){a-=b;a+=a>>31&mod;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline void ex_gcd(int a,int b,int &x,int &y){if(!b){x=1,y=0;return ;}ex_gcd(b,a%b,y,x);y-=a/b*x;
}
inline int inv(int a){assert(a);int x,y;ex_gcd(a,mod,x,y);return (x%mod+mod)%mod;
}struct func{int k,b;func(){}func(int _k,int _b):k(_k),b(_b){}friend func operator+(cs func &a,cs func &b){return func(add(a.k,b.k),add(a.b,b.b));}friend func operator-(cs func &a,cs func &b){return func(dec(a.k,b.k),dec(a.b,b.b));}friend func operator*(cs func &a,int b){return func(mul(a.k,b),mul(a.b,b));}inline int operator()(int x)cs{return add(mul(x,k),b);}inline func operator()(cs func &r)cs{return func(mul(k,r.k),add(mul(k,r.b),b));}
};inline func inv(cs func &a){assert(a.k);int iv=inv(a.k);return func(iv,mul(dec(0,a.b),iv));
}inline func pow_comp(func a,int b){func res(1,0);for(;b;b>>=1,a=a(a))if(b&1)res=res(a);return res;
}inline func pow_sum(cs func &a,int n){int k=a.k,b=a.b;if(k==1)return func(n,mul((ll)n*(n+1)/2%mod,b));int iv=inv(dec(1,k)),k1=mul(mul(k,iv),dec(1,power(k,n)));return func(k1,mul(mul(b,iv),dec(n,k1)));
}inline int calc(int n,int k,cs func &a,cs func &b,int s1,int s2){if(!k)return mul(mul(n,mul(a.b,s2)),inv(dec(1,a.k)));int p=n/k,t=n%k;func S2=pow_sum(a,p-1)*s2;Inc(S2.k,s1);func S1=S2+pow_comp(a,p)*s2;func ia=inv(a),ib=inv(b);func A=pow_comp(ia,p-1)(ib),B=ia(A);int tp=add(mul(S1.b,t),mul(S2.b,k-t));return add(tp,calc(k,t,A,B,S1.k,S2.k));
}signed main(){#ifdef zxyoifreopen("treasure.in","r",stdin);
#endifint T;scanf("%d",&T);while(T--){int n,k,p;scanf("%d%d%d",&n,&k,&p);if(p==1){int ans=n--;int t=n/k;Inc(ans,mul(k,(ll)t*(t-1)/2%mod));Inc(ans,mul(n-t*k+1,t));cout<<mul(ans,inv(n+1))<<"\n";}else cout<<mul(inv(n),calc(n,k,func(1,1),func(dec(1,p),1),1,1))<<"\n";} return 0;
}

【题目泛做】宝藏(期望)(类欧几里得)相关推荐

  1. 解题报告(十八)数论题目泛做(Codeforces 难度:2000 ~ 3000 + )

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...

  2. 牛客网暑期ACM多校训练营(第十场): H. Rikka with Ants(类欧几里得)

    链接:https://ac.nowcoder.com/acm/contest/148/H 来源:牛客网 题目描述 There are two small ants on Rikka's desk. I ...

  3. BJ模拟:超级绵羊抑或(类欧几里得)

    传送门 题意: 给定 n,a,b n , a , b n,a,b (n,a,b≤1e9) ( n , a , b ≤ 1 e 9 ) (n,a,b \le 1e9),求 ⊕n−1i=0(a+b∗i) ...

  4. [ZZOJ#31]类欧几里得

    [ZZOJ#31]类欧几里得 试题描述 这是一道模板题. 给出 \(a, b, c, n\),请你求出 \(\sum_{x=0}^n{\lfloor \frac{a \cdot x + b}{c} \ ...

  5. 类欧几里得(模板题推导)

    类欧几里得 设三个函数f(a,b,c,n)=∑i=0na×i+bc,g(a,b,c,n)=∑i=0ni×a×i+bc,h(a,b,c,n)=∑i=0n(a×i+bc)2f(a, b, c, n) = ...

  6. (转载)类欧几里得(知识点整理+板子总结)

    思路来源 类欧几里得算法_wwx233的博客-CSDN博客 类欧几里得算法 - cyz666 - 博客园 类欧几里得算法总结_DZYO的博客-CSDN博客(证明清楚详细) 数数[数位DP||类欧]_以 ...

  7. K. Easy Sigma(类欧几里得)

    K. Easy Sigma ∑i=1n(−1)⌊i×k⌋,(n≤109,k≤104)\sum_{i = 1} ^{n} (-1) ^{\lfloor i \times \sqrt k \rfloor} ...

  8. 数学期望和概率DP题目泛做(为了对应AD的课件)

    题1: Uva 1636 Headshot 题目大意: 给出一个000111序列,注意实际上是环状的.问是0出现的概率大,还是当前是0,下一个还是0的概率大. 问题比较简单,注意比较大小: A/C & ...

  9. FFT与多项式、生成函数题目泛做

    题目1 COGS 很强的乘法问题 高精度乘法用FFT加速 1 #include <cstdlib> 2 #include <iostream> 3 #include <a ...

最新文章

  1. 解决h5py\_init_.py:26:FutureWarning: Conversion of the second argument of issubdtype from `float`^……
  2. HDOJ---1273 漫步森林[图论]
  3. java中arges.length_java中的args.length
  4. 创建WebSocket服务器
  5. Spring Boot + Shiro 集成
  6. Serilog 最佳实践
  7. 解决eclipse无法解析导入org.eclipse.swt库
  8. 漫步数理统计十八——相关系数
  9. 输入一个十进制数N,将它转换成R进制数输出(运用递归实现)
  10. python自定义标识符_《Python 3程序开发指南(第2版•修订版)》——第2章 数据类型 2.1 标识符与关键字...
  11. 装箱拆箱的意义 java_Java中的装箱和拆箱深入理解
  12. 刘明计算机学院,西南大学计算机与信息科学学院研究生导师简介-刘明
  13. FFT算法实现——python
  14. 角度与弧度的转换 C语言
  15. 使用freemarker循环图片(附demo)
  16. matlab读取txt函数,matlab读取txt某一行
  17. 常用工具 [ubuntu 图像编辑软件]
  18. 18V降压3.3V的降压IC和LDO芯片方案,15V降压3.3V的降压IC和LDO芯片方案
  19. 【Skill】解决 QQ 邮箱无法更改发信人名称问题
  20. 比亚迪F6专用高清车载导航影音登场

热门文章

  1. CCRC中国网络安全审查技术与认证中心 物联网安全技术工程师(ISTE)开课通知
  2. stb_truetype解析ttf字体获取顶点信息
  3. Solidity 基础知识
  4. php伪协议语法,php文件包含漏洞(input与filter)
  5. 金融数据分析(九)模拟计算以MACD指标买入卖出信号进行股票交易而产生的收益
  6. Eigen/Matlab库矩阵运算方法
  7. 提升.NET技术水平,我从不内卷!
  8. PART 4 描述性统计分析
  9. 山东大学软件学院2021区块链考试回忆
  10. Vue——05-02组件的数据、为什么data要使用函数、父组件给子组件传递数据的三种写法、父传子以及传两种以上的值、默认值以及父传子的引用类型