[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++