百度之星第五题Rotate

传送门
百度之星第五题Rotate_第1张图片
怎么说呢?这题,难点有俩,第一个:扩展欧几里得(求逆元);第二个:求期望的过程有点难理解。
因为最后题目让咱们输出A/Bmod10^9+7,还非常友善地告诉了我们:A/Bmod10 ^9+7=A∗B ^−1mod10 ^9+7,
在这里插入图片描述

通过找到B模10 ^ 9+7的逆元 B^-1,就有(A/B)%10 ^9+7=(A*B ^-1)%10 ^9+7成立
下面讲解扩展欧几里得(没法插入pdf枯了,那就截图看看把)(不要嫌我字丑wwww)
百度之星第五题Rotate_第2张图片
百度之星第五题Rotate_第3张图片
百度之星第五题Rotate_第4张图片OKK难点一解决了,如果没有请goto"下面讲解扩展欧几里得",再看难点二也就是求期望:
百度之星第五题Rotate_第5张图片

感觉我画了个游泳圈hhhhh
这里我们从圆环内部向外看,也就是首先是分割份数最多的圆环,最后是最外层圆环,也就是说份数是递减的,然后每一层圆环的份数是ai,那么涂色区就是ai/2,然后这个涂色区被外面一圈的白色区或者涂色区包裹的可能性各占1/2,所以这一圈就有ai/4个,然后外面一圈就有ai+1/4个。【注:i+1是下标】但是还没完,要想构成联通块必须按照森林的思路来想,把刚刚内圈看作有ai/4个点,外面一圈看作有ai+1/4条边,众所周知森林的联通块数目=点-边,所以这一个内圈的有效联通块数目就是(ai - ai+1)/4。还有一个问题,就是最外圈,因为这时候内圈全部算完还差这个,我们知道,最外圈被分成an份,那么染色区就是an/2份,每个染色区有两条边,每条边在内圈白区和黑区的概率各是1/2,所以最外圈有效个数就是(an/2)* 2 / 2,也就是an/2
那么里里外外加起来,也就是
百度之星第五题Rotate_第6张图片
好了,程序可以写了:

#include
#include
using namespace std;
typedef long long ll;

const ll m = 1e9 + 7;
int a[20];
int t, n;

void exgcd(ll a, ll b, ll &x, ll &y){
	if(!b){		//把b做到1
		x = 1, y = 0;	//此时a就是gcd(a,b),但是这里我们不需要a
	}else{
		exgcd(b, a % b, y, x);	//辗转相除,并且x,y换位置
		y -= (a / b) * x;
	}
}

ll niyuan(ll a, ll b){		//ax≡1(mod b)求x,也就是解ax+by=1中的x
	ll x, y;
	exgcd(a, b, x, y);
	return (x + b) % b;		//得到(0,b)范围内的解
}

int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for (int i = 1; i <= n; ++i)
		{
			scanf("%d",&a[i]);
		}
		printf("%lld\n", (a[1] + a[n]) * niyuan(4, m) % m);
	}
	return 0;
}

舒服!数学也不过如此!奈斯,扩展欧几里得搞懂了,也会写程序了,昨天一下午+今天一上午=不亏不亏hhhhh
百度之星第五题Rotate_第7张图片
参考链接:
Hi Bestcoder
2020 年百度之星·程序设计大赛 - 初赛一题解
扩展欧几里得算法(详细推导+代码实现+应用)

最后,跪谢大佬!orz

你可能感兴趣的:(来打一把cf,gcd)