• [COCI 2009-2010 #6] XOR


    ( ext{bibi}) 时间到!

    这种题我能想出来就有鬼了。

    题目

    传送门

    解法

    有一个先导结论 ——

    假设选取的三角形集合为 (S),那么 (S) 中三角形相交形成的三角形的面积为:

    [f(S)=frac{1}{2}(min{x_i+y_i+r_i}-max x_i-max y_i) ]

    具体证明的话,懒得画图,就用文字叙述吧:

    • (x_i+y_i+r_i) 能表示三角形 (i) 斜边形成直线的截距。
    • 相交三角形的斜边截距最小,左下角横纵坐标均为最大。

    枚举所选三角形集合进行容斥:

    [ ext{Ans}=sum_{empty subsetneq Ssubseteq U}g(|S|)cdot f(S) ]

    其中 (g) 是要算的容斥系数,它一般只与所选集合 大小 有关。

    类似容斥原理的证明,我们设某个三角形被 (m) 个三角形包含,就有:

    [sum_{i=1}^m inom{m}{i}cdot g(i)=[2 mid m] ]

    左边那个很像二项式反演,于是我们令 (h(m)=[2 mid m])。就有:

    [h(m)=sum_{i=1}^m inom{m}{i}cdot g(i) ]

    [g(m)=sum_{i=1}^m (-1)^{m-i} inom{m}{i}h(i) ]

    [g(m)=sum_{i=1}^m (-1)^{m-i} inom{m}{i}[2 mid i] ]

    推到这里应该就可以了,我没有试过,可以预处理一下 (g)

    不过其实还可以化简。虽然 ([2 mid i]) 看上去很难搞,但有一个这样的式子:

    [(a+b)^n-(a-b)^n=sum_{i=0}^ninom{n}{i}a^{n-i}b^{i}-sum_{i=0}^n(-1)^{i}inom{n}{i}a^{n-i}b^{i} ]

    [=2sum_{i=0}^n [2 mid i]inom{n}{i}a^{n-i}b^i ]

    ((-1)^{m-i}) 肿么办呢?由于只有 ([2 mid i]) 有贡献,所有的 ((-1)^{m-i}) 都相当于 ((-1)^{m-1}),而且还可以添一个 (i=0)。所以可以改写为:

    [g(m)=(-1)^{m-1}sum_{i=0}^m [2 mid i]inom{m}{i} ]

    [=(-1)^{m-1} imes frac{(1+1)^m-(1-1)^m}{2}=(-2)^{m-1} ]

    然后直接枚举集合计算贡献。时间复杂度 (mathcal O(ncdot2^n))另外那个神仙三维差分还是算了吧。而且这题暴力数三角形完全可过好吧!

    代码

    #include <cstdio>
    #define print(x,y) write(x),putchar(y)
    
    template <class T>
    inline T read(const T sample) {
    	T x=0; char s; bool f=0;
    	while((s=getchar())>'9' or s<'0')
    		f|=(s=='-');
    	while(s>='0' and s<='9')
    		x=(x<<1)+(x<<3)+(s^48),
    		s=getchar();
    	return f?-x:x;
    }
    
    template <class T>
    inline void write(const T x) {
    	if(x<0) {
    		putchar('-'),write(-x);
    		return;
    	}
    	if(x>9) write(x/10);
    	putchar(x%10^48);
    } 
    
    #include <iostream>
    using namespace std;
    
    const int maxn=1300,inf=1e7;
    
    int x[20],y[20],r[20],c[20];
    int n,Pow[maxn];
    
    int main() {
    	n=read(9);
    	for(int i=1;i<=n;++i)
    		x[i]=read(9),y[i]=read(9),
    		r[i]=read(9),c[i]=x[i]+y[i]+r[i];
    	Pow[0]=1;
    	for(int i=1;i<=n;++i)
    		Pow[i]=Pow[i-1]*(-2);
    	double ans=0;
    	for(int i=0;i<(1<<n);++i) {
    		int minc=inf,maxx=-inf,maxy=-inf,cnt=0;
    		for(int j=1;j<=n;++j)
    			if(i>>j-1&1)
    				++cnt,
    				minc=min(minc,c[j]),
    				maxx=max(maxx,x[j]),
    				maxy=max(maxy,y[j]);
    		if(minc-maxx-maxy>=0)
    			ans+=1.0*(minc-maxx-maxy)*(minc-maxx-maxy)/2*Pow[cnt-1];
    	}
    	printf("%.1f
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    uniapp
    vue -element admin 修改request,headers添加参数
    uniapp
    css
    uniapp
    uniapp
    vue
    vue
    vue -element 修复select下拉框在移动端需要点击两次才能选中的问题
    vue
  • 原文地址:https://www.cnblogs.com/AWhiteWall/p/15107981.html
Copyright © 2020-2023  润新知