题目描述

  有\(n\)个方案,编号为\(1\ldots n\)。

  最开始你不知道每个方案的编号。

  你要按顺序提出这些方案。

  每一个时刻你要做以下事情:

   如果你阅读过下一个方案,就提出这个方案。

   否则随机选一个你还没有阅读过的方案,然后阅读这份方案。如果这份方案是你马上要提出的方案,就提出这份方案,否则把这份方案放回到桌子上。

  问你期望耗时。对\(p^k\)取模。

  \(p\leq {10}^5,np^k\leq {10}^{18}\)

题解

  考虑你要在哪种方案上面浪费一个单位的时间,那就是你选择的方案是你下一个要提出的方案。

  显然你会在其他方案上面浪费两个单位的时间。

  设\(f_i\)为还有\(i\)个未阅读的方案,提出所有方案需要的时间。

\[\begin{align}
f_n&=f_{n-1}+\frac{1}{n}+2\frac{n-1}{n}\\
f_n&=2n-\sum_{i=1}^n\frac{1}{i}
\end{align}
\]

  然后直接套用这题的做法就行了。

  时间复杂度:\(O(pk\log_p n)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef __int128 lll;
ll p;
ll mul(ll a,ll b,const ll &c)
{
return (lll)a*b%c;
}
ll fp(ll a,ll b){ll s=1;for(;b;b>>=1,a*=a)if(b&1)s*=a;return s;}
ll fp(ll a,ll b,const ll &c){ll s=1;for(;b;b>>=1,a=mul(a,a,c))if(b&1)s=mul(s,a,c);return s;}
int pri[1000010];
int b[1000010];
ll pw[1000010];
int cnt;
ll ss[100][100];
void getstirling(ll k,const ll &md)
{
ss[0][0]=1;
for(int i=1;i<=k;i++)
for(int j=1;j<=i;j++)
ss[i][j]=(ss[i-1][j-1]-mul(i-1,ss[i-1][j],md))%md;
}
ll gao(ll n,ll k,const ll &md)
{
ll s=(n+1)/(k+1);
ll v=s*(k+1);
for(ll i=n+1;i>=n-k+1;i--)
s=mul(s,(i==v?1:i),md);
return s;
}
void gets(ll *s,ll n,ll k,const ll &md)
{
s[0]=n;
for(int i=1;i<=k;i++)
{
s[i]=gao(n,i,md);
for(int j=0;j<i;j++)
s[i]=(s[i]-mul(ss[i][j],s[j],md))%md;
}
s[0]++;
}
ll s1[100];
ll s2[100];
ll g(ll n,const ll &md,ll k)
{
ll r=n%p;
getstirling(k,md);
gets(s1,n/p-1,k,md);
gets(s2,n/p,k,md);
ll res=0,s;
ll t=fp(p,k)-fp(p,k-1)-1;
for(int i=0;i<k;i++)
{
s=0;
pw[1]=1;
cnt=0;
for(int j=1;j<p;j++)
b[j]=0;
for(int j=2;j<p;j++)
{
if(!b[j])
{
pri[++cnt]=j;
pw[j]=fp(fp(j,i+1),t,md);
}
for(int k=1;k<=cnt&&j*pri[k]<p;k++)
{
b[j*pri[k]]=1;
pw[j*pri[k]]=mul(pw[j],pw[pri[k]],md);
if(j%pri[k]==0)
break;
}
}
for(int j=1;j<p;j++)
if(j<=r)
s=(s+mul(s2[i],pw[j],md))%md;
else
s=(s+mul(s1[i],pw[j],md))%md;
s=mul(s*(i&1?-1:1),fp(p,i),md);
res=(res+s)%md;
}
// fprintf(stderr,"G(%lld, %lld) = %lld\n",n,md,(res+md)%md);
return res;
}
ll f(ll n,const ll &md,ll k)
{
if(!n)
return 0;
return (g(n,md,k)+f(n/p,md*p,k+1)/p)%md;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
#endif
ll n,k;
scanf("%lld%lld%lld",&p,&k,&n);
const ll md=fp(p,k);
ll ans=f(n,md,k);
ans=(2*n-ans)%md;
ans=(ans+md)%md;
printf("%lld\n",ans);
return 0;
}

最新文章

  1. ubuntu系统(华硕笔记本)屏幕亮度用Fn控制的调节设置
  2. HTML 学习笔记 JavaScript(call方法详解)
  3. PRINCE2风险模块
  4. springmvc拦截器验证登录时间
  5. linux安装和配置 mysql、redis 过程中遇到的问题记录
  6. tc 146 2 RectangularGrid(数学推导)
  7. JavaScript 在不刷新或跳转页面的情况下改变当前浏览器地址栏上的网址
  8. Android SmartImageView框架的简单实用
  9. WebApp之Meta标签 (关闭自动识别数字为电话号码或邮箱之类)
  10. 11-TypeScript中的名称空间
  11. Elasticsearch JavaApi
  12. js中的观察者模式
  13. C++中String类的字符串分割实现
  14. C/C++ 控制台窗口暂停
  15. httpstatus类的状态有哪些
  16. MySQL——navicat 连接 mysql 出现1251Client does not support authentication protocol requested by server的解决方案
  17. 【java】之彻底明白进制转换
  18. Java 8 新日期时间 API
  19. window / Linux 下 Golang 开发环境的配置
  20. ES6-fetch

热门文章

  1. logstash安装及基础入门
  2. mysqldump 和mysqlbinlog
  3. H5 文本属性
  4. super关键字访问父类成员
  5. rabbitmq集群运维一点总结
  6. python 中的super()继承,搜索广度为先
  7. 集大软件工程15级结对编程week1
  8. 爬虫——scrapy框架
  9. TortoiseGit push免输密码
  10. Webbench、ab命令:做压力测试的工具和性能的监控工具