• [NOIP2016普及组]魔法阵


    题目:洛谷P2119、Vijos P2012、codevs5624。

    题目大意:有n件物品,每件物品有个魔法值。要求组成魔法阵(Xa,Xb,Xc,Xd),该魔法阵要满足Xa<Xb<Xc<Xd,Xb-Xa=2(Xd-Xc),并且Xb-Xa<(Xc-Xb)/3。求每件物品作为a、b、c、d的次数。

    解题思路:这真是一道锻炼思(bào)维(lì)能力的好(kēng)题!

    首先枚举魔法阵的每件物品,姿势好可得65(洛谷测)。

    然后是强(wěi)大(suǒ)的正解。

    首先利用桶排的思路保存各个魔法值。

    设Xd-Xc=t,则根据一系列推论可得:

    Xb-Xa=2t

    Xc-Xb>6t

    那么首先想到的就是枚举t,然后再枚举c、b,算出a、d,最后一交发现还是超时几个点!!是不是气的想砸电脑了?

    别急慢慢来。首先我们可以发现,t的枚举范围在1~n/9中即可。

    然后我们令d取满足条件的最小值(9t+2),a就只能取1(b可以根据a推出,不用考虑),那么如果d增加1,a就能选1、2,d增加2,a能取1、2、3……

    那么我们用一个sum记录当前a、b共有多少种选法,然后计算c、d,就不用再次枚举了。

    同理a、b取最大值,然后如此计算即可。

    满分拿到,感觉比网络流还难!!!

    C++ Code:

    #include<cstdio>
    #include<cctype>
    using namespace std;
    int n,m,cnt[15999]={0};
    int A[15999]={0},B[15999]={0},C[15999]={0},D[15999]={0},f[40004];
    inline int readint(){
    	char c=getchar();
    	int p=0;
    	for(;!isdigit(c);c=getchar());
    	for(;isdigit(c);c=getchar())p=(p<<3)+(p<<1)+(c^'0');
    	return p;
    }
    int main(){
    	m=readint(),n=readint();
    	for(int i=1;i<=n;++i){
    		f[i]=readint();
    		++cnt[f[i]];
    	}
    	for(int t=1;9*t<=m;++t){
    		int sum=0;
    		for(int d=t*9+2;d<=m;++d){
    			int c=d-t,b=d-7*t-1,a=d-9*t-1;
    			sum+=cnt[a]*cnt[b];
    			C[c]+=cnt[d]*sum;
    			D[d]+=cnt[c]*sum;
    		}
    		sum=0;
    		for(int a=m-t*9-1;a>=1;--a){
    			int b=a+2*t,c=a+8*t+1,d=a+9*t+1;
    			sum+=cnt[c]*cnt[d];
    			A[a]+=cnt[b]*sum;
    			B[b]+=cnt[a]*sum;
    		}
    	}
    	for(int i=1;i<=n;++i)printf("%d %d %d %d
    ",A[f[i]],B[f[i]],C[f[i]],D[f[i]]);
    	return 0;
    }
    
  • 相关阅读:
    上一篇、下一篇之实现思路
    sql优化
    简易的文件上传 tp5
    phpqrcode生成二维码
    php 发送邮件(2)qq邮箱开通
    php 发送邮件(1)代码逻辑
    SELECT list is not in GROUP BY clause and contains nonaggregated
    TP5 未定义变量:XXX
    CentOS 7下载
    FFT算法实现——基于GPU的基2快速傅里叶变换
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7502161.html
Copyright © 2020-2023  润新知