首页 > 其他 > 详细

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

时间:2015-02-04 00:20:34      阅读:601      评论:0      收藏:0      [点我收藏+]

http://www.lydsy.com/JudgeOnline/problem.php?id=3434

题意:n维坐标中要找c个点使得c个点在一条线上且每一维的坐标单调递增且不能超过每一维限定的值m[i](n<=11, 2<=c<=20, m[i]<=100000)

#include <bits/stdc++.h>
using namespace std;
const int N=100005, MD=10007;
int C[N][19], g[21][N], f[21][12][N], a[12], p[N], pcnt, mu[N], MN;
bool np[N];
inline void check(int &x) { if(x>=MD || x<=-MD) x%=MD; }
void init() {
	mu[1]=1;
	for(int i=2; i<=MN; ++i) {
		if(!np[i]) p[++pcnt]=i, mu[i]=-1;
		for(int j=1; j<=pcnt; ++j) {
			int t=i*p[j]; if(t>MN) break;
			np[t]=1;
			if(i%p[j]==0) { mu[t]=0; break; }
			mu[t]=-mu[i];
		}
	}
	C[0][0]=1;
	for(int i=1; i<=MN; ++i) {
		C[i][0]=1;
		for(int j=1; j<19; ++j) C[i][j]=C[i-1][j-1]+C[i-1][j], check(C[i][j]);
	}
	for(int c=2; c<=20; ++c)
		for(int i=1; i<=MN; ++i)
			for(int j=i, k=1; j<=MN; j+=i, ++k)
				g[c][j]+=C[i-1][c-2]*mu[k], check(g[c][j]);
	for(int i=1; i<=MN; ++i)
		for(int c=2; c<=20; ++c) {
			int t=1;
			for(int j=0; j<=11; ++j) {
				f[c][j][i]=t*g[c][i]+f[c][j][i-1];
				t*=i; check(t); check(f[c][j][i]);
			}
		}
}
int nn[1005], cc[1005], mm[1005][12], m[12], n, c;
typedef long long ll;
inline void cal(const int &xx) {
	memset(a, 0, sizeof a);
	a[0]=1;
	static int b, bb, i, t, k;
	for(k=0; k<n; ++k) {
		t=m[k]/xx;
		b=((ll)t*m[k])%MD; bb=-(((ll)t*(t+1))>>1)%MD;
		for(i=n; i>=1; --i)
			a[i]=(a[i]*b+a[i-1]*bb)%MD, check(a[i]);
		a[0]*=b; check(a[0]);
	}
}
int main() {
	int T;
	scanf("%d", &T);
	for(int cs=1; cs<=T; ++cs) {
		scanf("%d%d", &nn[cs], &cc[cs]);
		for(int i=0; i<nn[cs]; ++i)
			scanf("%d", &mm[cs][i]), MN=max(MN, mm[cs][i]);
	}
	init();
	for(int cs=1; cs<=T; ++cs) {
		n=nn[cs]; c=cc[cs];
		int mx=~0u>>1, ans=0;
		for(int i=0; i<n; ++i) m[i]=mm[cs][i], mx=min(mx, m[i]);
		for(int i=1, pos=0; i<=mx; i=pos+1) {
			pos=mx+1;
			for(int d=0; d<n; ++d) pos=min(pos, m[d]/(m[d]/i));
			cal(i);
			for(int d=0; d<=n; ++d) ans+=a[d]*(f[c][d][pos]-f[c][d][i-1]), check(ans);
		}
		printf("%d\n", ((ans%MD)+MD)%MD);
	}
	return 0;
}

  

题解:

我真的不想写公式了= =QAQ

本题最神的两个地方,也就是我没有想到的地方:

1、问题的转化:我们只需要在这些多维空间中确定两个端点,那么所有的点一定在这两个端点的线段上边就是了,而且不会重合。那么我们可以枚举两个端点的坐标差$i和j$(为了方便我们先设二维的,然后再推广),由于线端上整点的的数目就是$gcd(i, j)-1$(不包含端点),所以我们可以立即得到公式(待会写)。

2、公式的处理。由于推出公式后,会发现有一部分不能分块QAQ,因为是枚举$gcd$,而式子里边存在着乘法.....因此稍加处理(下边写)..

那么本题如果没有以上两点就是纯水题了.....

一下均设$m[i]<=m[j], i<=j$,因为这是没有影响的,下标是二维的情形

容易得到公式:

$$
\begin{align}
ans
= & \sum_{i=1}^{m[1]} \sum_{j=1}^{m[2]} (m[1]-i)(m[2]-j) \binom{(i, j)-1}{c-2} \\
= & \sum_{d=1}^{m[1]} \sum_{i=1}^{ \lfloor m[1]/d \rfloor } \sum_{j=1}^{ \lfloor m[2]/d \rfloor } [(i, j)=1] (m[1]-id)(m[2]-jd) \binom{d-1}{c-2} \\
\end{align}
$$

$$ f(d) = \sum_{i=1}^{ \lfloor m[1]/d \rfloor } \sum_{j=1}^{ \lfloor m[2]/d \rfloor }
[(i, j)=1] (m[1]-id)(m[2]-jd) $$
$$ F(d) = \sum_{i=1}^{ \lfloor m[1]/d \rfloor } \sum_{j=1}^{ \lfloor m[2]/d \rfloor }
(m[1]-id)(m[2]-jd) $$

$f(d)$表示范围内$i和j$的公约数只有最大公约数$d$时的对数,$F(d)$表示范围内$i和j$的公约数包括$d$的对数,那么由于最大公约数是所有公约数的约数,我们将有公约数$d$的所有最大公约数为$id$的都加起来就能得到$F(d)$,即

$$ F(d) = \sum_{d|n} f(n) $$

那么就能反演啦...即

$$ f(d) = \sum_{d|n} \mu ( \frac{n}{d} ) F(n) $$

 

最后推得:

$$
ans = \sum_{i=1}^{m[1]} \left( \lfloor \frac{m[1]}{i} \rfloor m[1] - i \frac{ \lfloor \frac{m[1]}{i} \rfloor ( \lfloor \frac{m[1]}{i} \rfloor + 1 ) }{2} \right) \left( \lfloor \frac{m[2]}{i} \rfloor m[2] - i \frac{ \lfloor \frac{m[2]}{i} \rfloor ( \lfloor \frac{m[2]}{i} \rfloor + 1 ) }{2} \right) \sum_{d|i} \mu ( \frac{i}{d} ) \binom{i-1}{c-2}
$$

发现后边和$m$是无关的= =,因此拓展就是将前边的东西合起来= =,即

$$
ans = \sum_{i=1}^{m[1]} \prod_{j=1}^{n} \left( \lfloor \frac{m[j]}{i} \rfloor m[j] - i \frac{ \lfloor \frac{m[j]}{i} \rfloor ( \lfloor \frac{m[j]}{i} \rfloor + 1 ) }{2} \right) \sum_{d|i} \mu ( \frac{i}{d} ) \binom{i-1}{c-2}
$$

$$ g(i) = \sum_{d|i} \mu ( \frac{i}{d} ) \binom{i-1}{c-2} $$

然后$O(nlnn)$的暴力求出$g(i)$你总会的吧= =但是关键是左边有个$i$ QAQ否则就能直接出解了..

发现其实是关于$i$的多项式...那么设系数向量$a$,且仅当$ \lfloor \frac{m[j]}{i} \rfloor 不变时 $,有

$$
\sum_{j=0}^{n} a_ji^j =
\prod_{j=1}^{n} \left( \lfloor \frac{m[j]}{i} \rfloor m[j] - i \frac{ \lfloor \frac{m[j]}{i} \rfloor ( \lfloor \frac{m[j]}{i} \rfloor + 1 ) }{2} \right)
$$

最后原式变为

$$
\begin{align}
ans_x
= & \sum_{i=1}^{m[1]} \sum_{j=0}^{n} a_ji^j g(i) \\
= & \sum_{j=0}^{n} a_j \sum_{i=1}^{m[1]} i^j g(i) \\
\end{align}
$$

然后暴力预处理你怕不怕= =

时间复杂度为:$O(clnnm+Tn^3\sqrt{m})$

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

原文:http://www.cnblogs.com/iwtwiioi/p/4271303.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!