【BZOJ3434】[Wc2014]时空穿梭

Description

Input

第一行包含一个正整数T,表示有T组数据求解
每组数据包含两行,第一行包含两个正整数N,C(c>=2),分别表示空间的
维数和需要选择的暂停点个数
第二行包含N个正整数,依次表示M1,M2....Mn

Output

有T行,每行一个非负整数,依次对应每组数据的答案。

Sample Input

3 
2 3 
3 4 
3 3 
3 4 4 
4 4 
5 9 7 8

Sample Output

2 
4 
846

HINT

样例数据第一组共有两种可行方案:一种是选择(1,1),( 2,2) ,( 3,3) ,另一种是选择 ( 1,2) ,( 2,3) ,( 3,4) 。

T<=1000,N<=11,C<=20,Mi<=100000

题解:BZOJ3518的加强版,推导过程倒不难,就是巨麻烦~~~

我们设由1号点指向c号点所构成的向量为(p1,p2...pn),那么我们枚举p1,p2...pn的值,于是中间的点可以在这条线段经过的所有整点中取,设d=gcd(p1,p2...pn),那么这条线段经过的整点数就是d-1(不算起点和终点)。并且这条线段还能在空间中不断平移,比如起点的第i位坐标可以在[1..mi-pi]中随便取。于是经过一番整理可以得到所求:

$ans=\sum\limits_{p_1=1}^{m_1}(m_1-p_1)\sum\limits_{p_2=1}^{m_2}(m_2-p_2)...\sum\limits_{p_n=1}^{m_n}(m_n-p_n)\times C_{gcd(p_1,p_2...p_n)-1}^{c-2}$

然后就是熟悉的莫比乌斯反演啦!我们设gcd=d,然后枚举d:

$ans=\sum\limits_{p_1=1}^{m_1}(m_1-p_1)\sum\limits_{p_2=1}^{m_2}(m_2-p_2)...\sum\limits_{p_n=1}^{m_n}(m_n-p_n)\times\sum\limits_{d=1}^{m_1}[d==gcd(p_1,p_2...p_n)] C_{d-1}^{c-2}\\=\sum\limits_{d=1}^{m_1}C_{d-1}^{c-2}\sum\limits_{p_1=1}^{\lfloor \frac {m_1} d \rfloor}(m_1-d\times p_1)\sum\limits_{p_2=1}^{\lfloor \frac {m_2} d \rfloor}(m_2-d\times p_2)...\sum\limits_{p_n=1}^{\lfloor \frac {m_n} d \rfloor}(m_n-d\times p_n)[gcd(p_1,p_2..p_n)==1]\\=\sum\limits_{d=1}^{m_1}C_{d-1}^{c-2}\sum\limits_{e=1}^{\lfloor \frac {m_1} d \rfloor}\mu(e)\sum\limits_{p_1=1}^{\lfloor \frac {m_1} {de} \rfloor}(m_1-de\times p_1)\sum\limits_{p_2=1}^{\lfloor \frac {m_2} {de} \rfloor}(m_2-de\times p_2)...\sum\limits_{p_n=1}^{\lfloor \frac {m_n} {de} \rfloor}(m_n-de\times p_n)$

令D=de:

$=\sum\limits_{D=1}^{m_1}\sum\limits_{d|D}C_{d-1}^{c-2}\mu(\frac D d)\prod\limits_{i=1}^n\sum\limits_{p_i=1}^{\lfloor \frac {m_i} {D} \rfloor}(m_i-D\times p_i)$

接着上等差数列求和公式:

$=\sum\limits_{D=1}^{m_1}\sum\limits_{d|D}C_{d-1}^{c-2}\mu(\frac D d)\prod\limits_{i=1}^n\frac {(2m_i-({\lfloor \frac {m_i} {D} \rfloor}+1)\times D){\lfloor \frac {m_i} {D} \rfloor}} 2$

到这里,我们就已经得到了一个$O(Tnm)$的做法,不过为了用前缀和来维护D,我们需要将右侧拆成关于D的多项式。因为我们过一会要对${\lfloor \frac {m_i} {D} \rfloor}$进行分块,所以我们可以将此时的${\lfloor \frac {m_i} {D} \rfloor}$看成常数,所以,右侧实质上就是一个n次的多项式,我们只需$O(n^2)$求出每一项的系数,然后套上D的j次方的前缀和即可。具体地,我们设第j项的系数为f(j):

$=\sum\limits_{D=1}^{m_1}\sum\limits_{d|D}C_{d-1}^{c-2}\mu(\frac D d)\prod\limits_{i=1}^n\frac {{\lfloor \frac {m_i} {D} \rfloor}} 2\sum\limits_{j=0}^nD^jf(j)\\=\sum\limits_{D=1}^{m_1}\prod\limits_{i=1}^n\frac {{\lfloor \frac {m_i} {D} \rfloor}} 2\sum\limits_{j=0}^nf(j)D^j\sum\limits_{d|D}C_{d-1}^{c-2}\mu(\frac D d)$

所以呢,我们要维护的就是$D^j\sum\limits_{d|D}C_{d-1}^{c-2}\mu(\frac D d)$的前缀和,设其为s[D][c-2][j],再套上分块就做完啦!

其实思路还是挺乱的,我们回顾一下全过程。

1.先预处理s数组
2.然后分块,对于每块,求出f数组
3.代入到多项式中计算答案

时间复杂度呢?

预处理s数组的复杂度=$O(cm\times ln_m+nmc)$
由于有n个m,所以我们一共分成了$n\sqrt m $块,每块我们都要用$n^2$的时间处理出f数组并用n的时间求和,所以总复杂度=$O(cm\times ln_m+nmc+Tn^3\sqrt m)$(这也能过?)

然而BZ上TLE了,不过UOJ上是AC的,辣鸡BZ。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int P=10007;
const int ine=5004;
const int N=100000;
int num;
bool np[N+5];
int pri[N],mu[N+5];
int c[N+5][22],s[N+5][21][12],sj[N+5][12],f[12],g[N+5][22];
int T,C;
int n,m[12],mn,ans;
int main()
{
register int i,j,k,last,tmp;
mu[1]=1;
for(i=2;i<=N;i++)
{
if(!np[i]) pri[++num]=i,mu[i]=-1;
for(j=1;j<=num&&i*pri[j]<=N;j++)
{
np[i*pri[j]]=1;
if(i%pri[j]==0) break;
mu[i*pri[j]]=-mu[i];
}
}
for(i=0;i<=N;i++) for(c[i][0]=j=1;j<=i&&j<=20;j++) c[i][j]=(c[i-1][j-1]+c[i-1][j])%P;
for(i=1;i<=N;i++) for(k=0,tmp=1;k<=11;k++,tmp=tmp*i%P) sj[i][k]=tmp;
for(j=0;j<=20;j++) for(i=1;i<=N;i++) if(mu[i]) for(k=i;k<=N;k+=i) g[k][j]=g[k][j]+mu[i]*c[k/i-1][j];
for(i=1;i<=N;i++) for(j=0;j<=20;j++) for(g[i][j]%=P,k=0;k<=11;k++)
s[i][j][k]=(s[i-1][j][k]+g[i][j]*sj[i][k])%P;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&C),mn=N,ans=0;
for(i=1;i<=n;i++) scanf("%d",&m[i]),mn=min(mn,m[i]);
for(i=1;i<=mn;i=last+1)
{
for(last=mn,j=1;j<=n;j++) last=min(last,m[j]/(m[j]/i));
for(tmp=j=1;j<=n;j++) tmp=tmp*(m[j]/i)%P*ine%P;
memset(f,0,sizeof(f)),f[0]=1;
for(j=1;j<=n;j++) for(k=j;k>=0;k--) f[k]=(f[k]*m[j]*2%P-f[k-1]*(m[j]/i+1))%P;
for(j=0;j<=n;j++) ans=(ans+tmp*f[j]%P*(s[last][C-2][j]-s[i-1][C-2][j]))%P;
}
printf("%d\n",(ans+P)%P);
}
return 0;
}//1 2 3 99997 99953

【BZOJ3434】[Wc2014]时空穿梭 莫比乌斯反演的更多相关文章

  1. BZOJ 3434 [WC2014]时空穿梭 (莫比乌斯反演)

    题面:BZOJ传送门 洛谷传送门 好难啊..反演的终极题目 首先,本题的突破口在于直线的性质.不论是几维的空间,两点一定能确定一条直线 选取两个点作为最左下和最右上的点! 假设现在是二维空间,选取了$ ...

  2. [WC2014]时空穿梭(莫比乌斯反演)

    https://www.cnblogs.com/CQzhangyu/p/7891363.html 不难推到$\sum\limits_{D=1}^{m_1}\sum\limits_{d|D}C_{d-1 ...

  3. UOJ#54 BZOJ3434 [WC2014]时空穿梭

    题目描述 小 X 驾驶着他的飞船准备穿梭过一个 \(n\) 维空间,这个空间里每个点的坐标可以用 \(n\) 个实数表示,即 \((x_1,x_2,\dots,x_n)\). 为了穿过这个空间,小 X ...

  4. BZOJ3434 [Wc2014]时空穿梭

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  5. BZOJ3434 WC2014时空穿梭(莫比乌斯反演)

    考虑枚举相邻点距离差的比例.显然应使比例值gcd为1以保证不重复统计.确定比例之后,各维坐标的方案数就可以分开考虑.设比例之和为k,则若坐标上限为m,该维坐标取值方案数即为Σm-ki (i=1~⌊m/ ...

  6. UOJ 54 【WC2014】时空穿梭——莫比乌斯反演

    题目:http://uoj.ac/problem/54 想写20分. Subtask 2 就是枚举4个维度的值的比例,可算对于一个比例有多少个值可以选,然后就是组合数.结果好像不对. 因为模数太小,组 ...

  7. [WC2014]时空穿梭

    这才叫莫比乌斯反演题. 一.题目 点此看题 二.解法 也没有什么好的思路,我们不妨把暴力柿子写出来,我们想枚举直线,但是这道题不能枚举直线的斜率,所以就要用整数来表示直线,我们不妨枚举出发点和终止点的 ...

  8. 【BZOJ】3434: [Wc2014]时空穿梭

    http://www.lydsy.com/JudgeOnline/problem.php?id=3434 题意:n维坐标中要找c个点使得c个点在一条线上且每一维的坐标单调递增且不能超过每一维限定的值m ...

  9. 莫比乌斯反演题表II

    bzoj3994:[SDOI2015]约数个数和 **很好推+有个小结论bzoj3309:DZY Loves Math ***很好推+线筛某函数/卡常bzoj4816:[Sdoi2017]数字表格 * ...

随机推荐

  1. IS支持解析json

    1. MIME设置:在IIS的站点属性的HTTP头设置里,选MIME 映射中点击”文件类型”-”新类型”,添加一个文件类型:关联扩展名:*.json内容类型(MIME):application/x-j ...

  2. MySql C++调用库Connector/c++编译 和 接口封装【三】Connector/c++ 使用总结及封装

    工程需要加上各个路径: 库使用需要几个文件: 1.include 文件夹 c/c++ /常规/附加包含目录 Connector/c++ 的安装版里面的Include 文件夹.或者把 /driver以及 ...

  3. JavaScript初学者福利!必须收藏的24条小技巧

    JavaScript初学者福利!必须收藏的24条小技巧 前端小编 发布于 2013-12-15 22:52 查看数: 2343 评论数: 6 帖子模式 这篇文章将回顾JavaScript的知识 !如果 ...

  4. 也谈谈js的压缩,jquery压缩。【转】

    问题缘由: 负责公司的开发平台研发工作,考虑的知识产权的保护工作,必须要考虑java的加密技术和js脚本的加密技术.在目前java加密很容易破解的情况下,还是先搞定js的加密和压缩,一方面可以提高页面 ...

  5. C语言 格式化输出--%m.n

    格式字符:格式字符用以指定输出项的数据类型和输出格式. ①d格式:用来输出十进制整数(int).有以下几种用法: %d:按整型数据的实际长度输出. %m.nd:m为指定的输出字段的宽度,n定义为实际输 ...

  6. Linux 精确获取指定目录对应的块的剩余空间

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/statfs ...

  7. Git:如何为项目设置自己的user name/email

    在项目根目录下查找  .git/config . 打开,添加如下内容(值换成你自己的名字和邮箱)即可: [user] name = Larry email = larry_zeal@163.com

  8. C++ 数据封装

    C++ 数据封装所有的 C++ 程序都有以下两个基本要素: 程序语句(代码):这是程序中执行动作的部分,它们被称为函数.程序数据:数据是程序的信息,会受到程序函数的影响.封装是面向对象编程中的把数据和 ...

  9. Blend for Visual Studio 2013

    软件开发中为了使设计师和程序员“并行”工作并直接参与到程序的开发中来. 1.在网络程序开发团队中,草图设计后,设计师们可以使用HTML.CSS.JavaScript直接生成UI,程序员则在这个UI产生 ...

  10. 【JavaScript】使用setInterval()函数作简单的轮询操作

    轮询(Polling)是一种CPU决策怎样提供周边设备服务的方式,又称"程控输出入"(Programmed I/O). 轮询法的概念是.由CPU定时发出询问.依序询问每个周边设备是 ...