【UOJ448】【集训队作业2018】人类的本质 min_25筛
题目大意
给你 \(n,m\),求
\]
对 \({10}^9+7\) 取模。
\(nm\leq {10}^9\)
题解
先推一下式子:
=\sum_{i=1}^n\sum_{x_1,x_2,\ldots,x_m=1}^i\frac{i}{\gcd(\frac{i}{\gcd(i,x_1)},\frac{i}{\gcd(i,x_2)},\ldots,\frac{i}{\gcd(i,x_m)})}\\
\]
然后枚举 \(y_j=\frac{i}{\gcd(i,x_j)}\)。对于一个 \(y_j\),有多少个满足要求的 \(x_j\) 呢?
\gcd(i,x_j)=\frac{i}{y_j}\\
\gcd(y_j,\frac{x_j}{y_j})=1\\
\]
所以有 \(\varphi(y_j)\) 个。
\]
记
\]
容易发现 \(f(n)\) 是积性函数。
=\sum_{j=0}^kg(j)\sum_{i=0}^jp^{k-i}\mu(\frac{j}{i})\\
g(j)=\begin{cases}
p^{km}&,j=1\\
(p^k-p^{j-1})^m&,2\leq j\leq k
\end{cases}\\
\]
=\sum_{x_1,x_2,\ldots,x_m=0}^{k}p^{\max(x_1,x_2,\ldots,x_m)}\prod_{j=1}^m\varphi(p^{k-x_j})\\
=\sum_{i=0}^kp^i(g(i)-g(i-1))\\
g(i)=\sum_{x_1,x_2,\dots,x_m=0}^i\prod_{j=1}^m\varphi(p^{k-x_j})\\
=\prod_{j=1}^m(\sum_{l=0}^i\varphi(p^{k-l}))\\=
\begin{cases}
p^{km}&,i=k\\
(p^k-p^{k-1-i})^m&,0\leq i<k
\end{cases}\\
f(p^{k+1})=p^mf(p^k)-p^k(p^{(k+1)m}-(p^{k+1}-1)^m)+p^{k+1}(p^{(k+1)m}-(p^{k+1}-1)^m)\\
=p^mf(p^k)+p^k(p-1)(p^{(k+1)m}-(p^{k+1}-1)^m)
\]
当 \(n\leq {10}^7\) 的时候可以线性筛算出 \(f(1)\sim f(n)\)。
时间复杂度:\(O(n(1+\frac{\log m}{\log n}))\)
当 \(n\) 大的时候:
=(1-p)(p-1)^m+p^{m+1}\\
=p^{m+1}-(p-1)^{m+1}\\
=-\sum_{i=0}^m{(-1)}^{m+1-i}p^i\binom{m+1}{i}\\
=\sum_{i=0}^m{(-1)}^{m-i}p^i\binom{m+1}{i}
\]
就可以上 min_25 筛了。
时间复杂度:\(O(\frac{n^{\frac{3}{4}}}{\log n}m+\sqrt nm^2)\)
代码
这个代码有些东西没有预处理,时间复杂度可能比上面写的高一些。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<functional>
#include<cmath>
#include<vector>
#include<assert.h>
//using namespace std;
using std::min;
using std::max;
using std::swap;
using std::sort;
using std::reverse;
using std::random_shuffle;
using std::lower_bound;
using std::upper_bound;
using std::unique;
using std::vector;
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef std::pair<int,int> pii;
typedef std::pair<ll,ll> pll;
void open(const char *s){
#ifndef ONLINE_JUDGE
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
void open2(const char *s){
#ifdef DEBUG
char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
#endif
}
int rd(){int s=0,c,b=0;while(((c=getchar())<'0'||c>'9')&&c!='-');if(c=='-'){c=getchar();b=1;}do{s=s*10+c-'0';}while((c=getchar())>='0'&&c<='9');return b?-s:s;}
void put(int x){if(!x){putchar('0');return;}static int c[20];int t=0;while(x){c[++t]=x%10;x/=10;}while(t)putchar(c[t--]+'0');}
int upmin(int &a,int b){if(b<a){a=b;return 1;}return 0;}
int upmax(int &a,int b){if(b>a){a=b;return 1;}return 0;}
const ll p=1000000007;
ll fp(ll a,ll b)
{
ll s=1;
for(;b;b>>=1,a=a*a%p)
if(b&1)
s=s*a%p;
return s;
}
int n,m;
namespace gao1
{
const int N=10000010;
int f[N];
int pw[N];
bool b[N];
int pri[N];
int c[N];
int cnt;
void gao()
{
f[1]=1;
pw[1]=1;
for(int i=2;i<=n;i++)
{
if(!b[i])
{
pri[++cnt]=i;
pw[i]=fp(i,m);
}
for(int j=1;j<=cnt&&i*pri[j]<=n;j++)
{
b[i*pri[j]]=1;
pw[i*pri[j]]=(ll)pw[i]*pw[pri[j]]%p;
if(i%pri[j]==0)
break;
}
}
for(int i=2;i<=n;i++)
{
if(!b[i])
{
c[i]=i;
f[i]=fp(i,m+1)-fp(i-1,m+1);
}
for(int j=1;j<=cnt&&pri[j]<=i&&i*pri[j]<=n;j++)
{
int v=i*pri[j];
if(i%pri[j]==0)
{
c[v]=c[i]*pri[j];
if(c[v]==v)
f[v]=((ll)pw[pri[j]]*f[i]+(ll)i*(pri[j]-1)*(pw[v]-pw[v-1]))%p;
else
f[v]=(ll)f[c[v]]*f[v/c[v]]%p;
break;
}
c[v]=pri[j];
f[v]=(ll)f[i]*f[pri[j]]%p;
}
}
ll ans=0;
for(int i=1;i<=n;i++)
ans+=f[i];
ans=(ans%p+p)%p;
printf("%lld\n",ans);
}
}
namespace gao2
{
const int N=100010;
ll inv[N],fac[N],ifac[N];
ll binom(int x,int y)
{
return x>=y&&y>=0?fac[x]*ifac[y]%p*ifac[x-y]%p:0;
}
int _;
int b[N],pri[N],cnt;
void init()
{
inv[1]=fac[0]=fac[1]=ifac[0]=ifac[1]=1;
for(int i=2;i<=100000;i++)
{
inv[i]=-p/i*inv[p%i]%p;
fac[i]=fac[i-1]*i%p;
ifac[i]=ifac[i-1]*inv[i]%p;
}
for(int i=2;i<=_;i++)
{
if(!b[i])
pri[++cnt]=i;
for(int j=1;j<=cnt&&i*pri[j]<=_;j++)
{
b[i*pri[j]]=1;
if(i%pri[j]==0)
break;
}
}
}
ll pw[N],s[N];
void init(int x)
{
pw[1]=1;
for(int i=2;i<=x+2;i++)
{
if(!b[i])
pw[i]=fp(i,x);
for(int j=1;j<=cnt&&i*pri[j]<=n&&pri[j]<=i;j++)
{
pw[i*pri[j]]=pw[i]*pw[pri[j]]%p;
if(i%pri[j]==0)
break;
}
}
for(int i=1;i<=x+2;i++)
s[i]=(s[i-1]+pw[i])%p;
}
ll pre[N],suf[N];
ll calc(int x,int y)
{
if(x<=y+2)
return s[x];
pre[0]=1;
for(int i=1;i<=y+2;i++)
pre[i]=pre[i-1]*(x-i)%p;
suf[y+3]=1;
for(int i=y+2;i>=1;i--)
suf[i]=suf[i+1]*(x-i)%p;
ll res=0;
for(int i=1;i<=y+2;i++)
res=(res+s[i]*pre[i-1]%p*suf[i+1]%p*ifac[i-1]%p*ifac[y+2-i]%p*((y+2-i)&1?-1:1))%p;
return res;
}
ll s1[N],s2[N],ans1[N],ans2[N];
void gao(int x)
{
init(x);
calc(3,x);
for(int i=1;i<=_;i++)
s1[i]=(fp(i,x)+s1[i-1])%p;
for(int i=1;n/i>_;i++)
s2[i]=calc(n/i,x);
for(int i=1;i<=cnt;i++)
{
ll v=fp(pri[i],x);
int j;
for(j=1;n/j/pri[i]>_&&n/j>=(ll)pri[i]*pri[i];j++)
s2[j]=(s2[j]-v*(s2[j*pri[i]]-s1[pri[i]-1]))%p;
for(;n/j>_&&n/j>=(ll)pri[i]*pri[i];j++)
s2[j]=(s2[j]-v*(s1[n/j/pri[i]]-s1[pri[i]-1]))%p;
for(j=_;j>=(ll)pri[i]*pri[i];j--)
s1[j]=(s1[j]-v*(s1[j/pri[i]]-s1[pri[i]-1]))%p;
}
}
ll g(int z,int x,int y)
{
if(z<0)
return 0;
return z==y?fp(x,(ll)y*m):fp(fp(x,y)-fp(x,y-z-1),m);
}
ll get(int x,int y)
{
ll res=0;
for(int i=0;i<=y;i++)
res=(res+fp(x,i)*(g(i,x,y)-g(i-1,x,y)))%p;
return res;
}
ll solve(ll x,int y)
{
if(x<=1||x<pri[y])
return 0;
if(y>cnt)
return (x<=_?ans1[x]:ans2[n/x])-ans1[_];
ll res=(x<=_?ans1[x]:ans2[n/x])-ans1[pri[y]-1];
for(int i=y;i<=cnt&&(ll)pri[i]*pri[i]<=x;i++)
{
ll x1=x/pri[i];
for(int j=1;x1>=pri[i];j++,x1/=pri[i])
res=(res+solve(x1,i+1)*get(pri[i],j)+get(pri[i],j+1))%p;
}
return res;
}
void gao()
{
_=sqrt(n)+0.5;
init();
for(int i=0;i<=m;i++)
{
gao(i);
ll v=binom(m+1,i)*((m-i)&1?-1:1);
for(int i=1;i<=_;i++)
ans1[i]=(ans1[i]+v*s1[i])%p;
for(int i=1;n/i>_;i++)
ans2[i]=(ans2[i]+v*s2[i])%p;
}
ll ans=solve(n,1);
ans++;
ans=(ans%p+p)%p;
printf("%lld\n",ans);
}
}
int main()
{
open("c");
scanf("%d%d",&n,&m);
if(n<=1e7)
gao1::gao();
else
gao2::gao();
return 0;
}
【UOJ448】【集训队作业2018】人类的本质 min_25筛的更多相关文章
- UOJ #449. 【集训队作业2018】喂鸽子
UOJ #449. [集训队作业2018]喂鸽子 小Z是养鸽子的人.一天,小Z给鸽子们喂玉米吃.一共有n只鸽子,小Z每秒会等概率选择一只鸽子并给他一粒玉米.一只鸽子饱了当且仅当它吃了的玉米粒数量\(≥ ...
- [UOJ422][集训队作业2018]小Z的礼物——轮廓线DP+min-max容斥
题目链接: [集训队作业2018]小Z的礼物 题目要求的就是最后一个喜欢的物品的期望得到时间. 根据$min-max$容斥可以知道$E(max(S))=\sum\limits_{T\subseteq ...
- 【UOJ#450】【集训队作业2018】复读机(生成函数,单位根反演)
[UOJ#450][集训队作业2018]复读机(生成函数,单位根反演) 题面 UOJ 题解 似乎是\(\mbox{Anson}\)爷的题. \(d=1\)的时候,随便怎么都行,答案就是\(k^n\). ...
- 【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)
[UOJ#422][集训队作业2018]小Z的礼物(min-max容斥,轮廓线dp) 题面 UOJ 题解 毒瘤xzy,怎么能搬这种题当做WC模拟题QwQ 一开始开错题了,根本就不会做. 后来发现是每次 ...
- UOJ#418. 【集训队作业2018】三角形
#418. [集训队作业2018]三角形 和三角形没有关系 只要知道儿子放置的顺序,就可以直接模拟了 记录历史最大值 用一个pair(a,b):之后加上a个,期间最大值为增加b个 合并? A1+A2= ...
- 2019.2.25 模拟赛T1【集训队作业2018】小Z的礼物
T1: [集训队作业2018]小Z的礼物 我们发现我们要求的是覆盖所有集合里的元素的期望时间. 设\(t_{i,j}\)表示第一次覆盖第i行第j列的格子的时间,我们要求的是\(max\{ALL\}\) ...
- [集训队作业2018]蜀道难——TopTree+贪心+树链剖分+链分治+树形DP
题目链接: [集训队作业2018]蜀道难 题目大意:给出一棵$n$个节点的树,要求给每个点赋一个$1\sim n$之内的权值使所有点的权值是$1\sim n$的一个排列,定义一条边的权值为两端点权值差 ...
- UOJ#422. 【集训队作业2018】小Z的礼物
#422. [集训队作业2018]小Z的礼物 min-max容斥 转化为每个集合最早被染色的期望时间 如果有x个选择可以染色,那么期望时间就是((n-1)*m+(m-1)*n))/x 但是x会变,中途 ...
- UOJ#428. 【集训队作业2018】普通的计数题
#428. [集训队作业2018]普通的计数题 模型转化好题 所以变成统计有标号合法的树的个数. 合法限制: 1.根标号比子树都大 2.如果儿子全是叶子,数量B中有 3.如果存在一个儿子不是叶子,数量 ...
随机推荐
- 关于C# 中的布尔运算符 "&" "|” 与 其类似的条件布尔运算符 "&&" "||" 区别说明。
运算符使用说明如下: 分隔符 ———————————————————————————— 分隔符 ———————————————————————————— 上述两个运算符的结果与&和 | 完全 ...
- Doctype的作用?严格模式与混合模式,如何触发者这两种模式,区分它们有何意义?
Doctype作用?严格模式与混合模式,如何触发者这两种模式,区分它们有何意义? 1.1 Doctype作用 <!DOCTYPE>声明叫做文件类型定义(DTD),声明的作用为了告诉浏览器该 ...
- Python笔记-高级特性
1.迭代 如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration). 如果要迭代value,可以用for value in d ...
- socket通信如何处理每次包长度不定问题
说起来,这是一个漫长的问题: 客户端和服务器通信的结构是:包头+数据长度+数据 客户端请求服务器发送200包数据.包头=request:长度=4(一个int),数据=200: 服务器在收到客户端的请求 ...
- Git的安装与配置
在安装Git之前,首先要下载Git安装包. 下载地址:https://gitforwindows.org/ 下载完后打开安装:如下步骤 按着以上步骤安装完成 ...
- rabbitmq之简述HAProxy配置集群过程
简介 HAProxy是一款提供高可用性.负载均衡以及基于TCP和HTTP应用的代理软件,HAProxy是完全免费的.借助HAProxy可以快速并且可靠的提供基于TCP和HTTP应用的代理解决方案.HA ...
- timers模块
timers模块 var timers = require('timers'); function A() { //将A对象注册到定时器里 timers.enroll(); //进行激活,如果不激活, ...
- fastJson反序列化异常,JSONException: expect ':' at 0, actual =
com.alibaba.fastjson.JSONException: expect , actual = at com.alibaba.fastjson.parser.DefaultJSONPars ...
- 对多条件进行组合,生成笛卡尔积的用例集合的python代码实现
做专项测试需要对一些因素进行组合的测试,这里组合起来后数据量可能很大,我们可以用python来代劳 代码有优化空间,目前先用着. ************************代码开始******* ...
- python全局解释器GIL
1.什么是进程: 进程是竞争计算机资源的基本单位.对于单核CPU来讲,同一时间只能有一个进程在运行,所以当我们开启多个应用时,操作系统需要根据进程调度算法去在不同的应用程序之间切换,而不同的进程之间切 ...