[CSP-S模拟测试]:打表(猜测题意+结论)

题目传送门(内部题139)


输入格式

  第一行两个整数$k,ans$,表示内存地址$A$的位数,以及答案所在的内存地址。
  接下来一行$2^k$个整数,分别表示内存地址$0...2^k-1$上的值。


输出格式

  输出一行一个正整数,表示这个程序输出结果的期望在模$10^9+7$意义下的值。


样例

样例输入1:

2 3
3 2 1 0

样例输出1:

500000005

样例输入2:

3 4
1 4 2 7 5 7 1 4

样例输出2:

125000003


数据范围与提示

样例解释:

  第一组样例的答案是$\frac{3}{2}$,第二组样例的答案是$\frac{17}{8}$。

数据范围:

  令内存内的数值的值域为$[0,v]$中的整数。
  对于$20\%$的数据,$k\leqslant 4$。
  对于$50\%$的数据,$k\leqslant 12$。
  对于另$20\%$的数据,$v=1$。
  对于$100\%$的数据,$1\leqslant k\leqslant 18,v=10^9,0\leqslant ans<2^k$。


题解

先来解释一下题意。

那个差是绝对值……

$ans$是下标

别问我怎么看出来的,我没看出来!!!

用$DeepinC$说的话就是:“用脚写题面的出题人。”

于是就有了个结论……

答案就是:

$$\frac{\sum\limits_{i=0}^{2^k-1}|v_i-v_{ans}|}{2^k}$$

时间复杂度:$\Theta(2^k)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
const int mod=1000000007;
int k,s;
int v[300000];
long long sum,ans;
long long qpow(long long x,long long y)
{
	long long res=1;
	while(y)
	{
		if(y&1)res=res*x%mod;
		x=x*x%mod;y>>=1;
	}
	return res;
}
int main()
{
	freopen("table.in","r",stdin);
	freopen("table.out","w",stdout);
	scanf("%d%d",&k,&s);
	for(int i=0;i<(1<<k);i++)scanf("%d",&v[i]);
	for(int i=0;i<(1<<k);i++)sum=(sum+abs(v[i]-v[s]))%mod;
	int wzc=1<<k;
	int gcd=__gcd(1LL*wzc,sum);
	sum/=gcd;wzc/=gcd;
	printf("%lld",sum*qpow(wzc,mod-2)%mod);
	return 0;
}

rp++

posted @ 2019-11-10 17:00  HEOI-动动  阅读(264)  评论(0编辑  收藏  举报