NOIP2016P4 魔法阵 题解

(题目描述略)

设魔法值为 j 物品 n u m j num_j numj 个,则魔法阵 x a , x b , x c , x d x_a, x_b, x_c, x_d xa,xb,xc,xd 对于 A, B, C, D 物品贡献分别为 n u m x b ∗ n u m x c ∗ n u m x d , n u m x a ∗ n u m x c ∗ n u m x d , n u m x a ∗ n u m x b ∗ n u m x d , n u m x a ∗ n u m x b ∗ n u m x c num_{xb} * num_{xc} * num_{xd}, num_{xa} * num_{xc} * num_{xd}, num_{xa} * num_{xb} * num_{xd}, num_{xa} * num_{xb} * num_{xc} numxbnumxcnumxd,numxanumxcnumxd,numxanumxbnumxd,numxanumxbnumxc。设 i = x d − x c i = x_d - x_c i=xdxc,则 x b − x a = 2 i x_b - x_a = 2i xbxa=2i x c − x b > 6 i x_c - x_b > 6i xcxb>6i x d − x b > 7 i x_d - x_b > 7i xdxb>7i x c − x a > 8 i x_c - x_a > 8i xcxa>8i x d − x a > 9 i x_d - x_a > 9i xdxa>9i。枚举 i ∈ [ 1 , ⌊ n − 1 9 ⌋ ] i \in [1, \lfloor \frac{n - 1}9 \rfloor] i[1,9n1],并枚举 x a , x d x_a, x_d xa,xd 使得 1 ≤ x a ≤ x d ≤ n 1 ≤ x_a ≤ x_d ≤ n 1xaxdn x d − x a > 9 i x_d - x_a > 9i xdxa>9i,由 x b = x a + 2 i x_b = x_a + 2i xb=xa+2i x c = x d − i x_c = x_d - i xc=xdi 得出每组可能 x a , x b , x c , x d x_a, x_b, x_c, x_d xa,xb,xc,xd 统计即可,这样可得 85 分。

对于满分算法,考虑当 x a = n − 9 i − 1 x_a = n - 9i - 1 xa=n9i1,即 x b = n − 7 i − 1 x_b = n - 7i -1 xb=n7i1 时,相应 { x c = n − i x d = n \begin{cases} x_c = n - i \\ x_d = n \end{cases} {xc=nixd=n;当 { x a = n − 9 i − 2 x b = n − 7 i − 2 \begin{cases} x_a = n - 9i - 2 \\ x_b = n - 7i - 2 \end{cases} {xa=n9i2xb=n7i2 时,相应 { x c = n − i x d = n \begin{cases} x_c = n - i \\ x_d = n \end{cases} {xc=nixd=n { x c = n − 1 − i x d = n − 1 \begin{cases} x_c = n - 1 - i \\ x_d = n - 1 \end{cases} {xc=n1ixd=n1。一般的,当 { x a = n − 9 i − j x b = n − 7 i − j ( 1 ≤ j &lt; n − 9 i ) \begin{cases} x_a = n - 9i - j \\ x_b = n - 7i - j \end{cases}(1 ≤ j &lt; n - 9i) {xa=n9ijxb=n7ij(1j<n9i) 时,相应 x c , x d x_c, x_d xc,xd 解集为 { x a = n − 9 i − j + 1 x b = n − 7 i − j + 1 \begin{cases} x_a = n - 9i - j + 1 \\ x_b = n - 7i - j + 1 \end{cases} {xa=n9ij+1xb=n7ij+1 解集和 { x c = n − j + 1 − i x d = n − j + 1 \begin{cases} x_c = n - j + 1 - i \\ x_d = n - j + 1 \end{cases} {xc=nj+1ixd=nj+1 的并集,对于 A, B 物品贡献分别为 n u m x b ∗ ∑ k = 1 j ( n u m n − k + 1 − i ∗ n u m n − k + 1 ) num_{xb} * \sum_{k = 1}^j (num_{n - k + 1 - i} * num_{n - k + 1}) numxbk=1j(numnk+1inumnk+1) n u m x a ∗ ∑ k = 1 j ( n u m n − k + 1 − i ∗ n u m n − k + 1 ) num_{xa} * \sum_{k = 1}^j (num_{n - k + 1 - i} * num_{n - k + 1}) numxak=1j(numnk+1inumnk+1),而 ∑ k = 1 j ( n u m n − k + 1 − i ∗ n u m n − k + 1 ) = ∑ k = 1 j − 1 ( n u m n − k + 1 − i ∗ n u m n − k + 1 ) + n u m n − j + 1 − i ∗ n u m n − j + 1 \sum_{k = 1}^j (num_{n - k + 1 - i} * num_{n - k + 1}) = \sum_{k = 1}^{j - 1} (num_{n - k + 1 - i} * num_{n - k + 1}) + num_{n - j + 1 - i} * num_{n - j + 1} k=1j(numnk+1inumnk+1)=k=1j1(numnk+1inumnk+1)+numnj+1inumnj+1,前者可递推得到。

代码如下:

#include<stdio.h>
#define MAX_M (40005)
#define MAX_N (15005)
int num[MAX_N],suma[MAX_N],sumb[MAX_N],sumc[MAX_N],sumd[MAX_N],x[MAX_M];
int main()
{
	freopen("magic.in","r",stdin);
	freopen("magic.out","w",stdout);
	int k,m,n;
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++)
		num[i]=suma[i]=sumb[i]=sumc[i]=sumd[i]=0;
	for(int i=1;i<=m;i++)
		scanf("%d",&x[i]),num[x[i]]++;
	for(int i=1;i*9<n-1;i++)
	{
		k=0;
		for(int id=n;id-i*9>1;id--)
			k+=num[id-i]*num[id],
			suma[id-i*9-1]+=num[id-i*7-1]*k,
			sumb[id-i*7-1]+=num[id-i*9-1]*k;
		k=0;
		for(int ia=1;ia+i*9<n;ia++)
			k+=num[ia]*num[ia+i*2],
			sumc[ia+i*8+1]+=num[ia+i*9+1]*k,
			sumd[ia+i*9+1]+=num[ia+i*8+1]*k;
	}
	for(int i=1;i<=m;i++)
		printf("%d %d %d %d\n",suma[x[i]],sumb[x[i]],sumc[x[i]],sumd[x[i]]);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值