其他分享
首页 > 其他分享> > "蔚来杯"2022牛客暑期多校训练营4

"蔚来杯"2022牛客暑期多校训练营4

作者:互联网

N-Particle Arts

题意

有n个粒子,第i个粒子有\(a_i\)的能量。粒子之间不停的碰撞,当两个分别具有能量a,b的两个粒子相撞之后这两个粒子会消失,同时产生两个能量分别为a&b,a|b,的粒子。当这些粒子的状态稳定之后求它的能量的方差是多少。(稳定是指方差不再改变)

数据范围

\(1 <= n <= 1e5 , 0 <= a_i < 2^{15}\)

思路

性质一:\(a \& b + a|b = a + b\),所以能量的平均值\(E(x)\)不变

性质二:方差公式有\(\sigma^2 = \frac{1}{n}\sum(a_i-E(x))^2\) 同时还有\(D(x) = E(x^2) - {E(x)}^2\)这道题就要用第二个,不然会溢出。

性质三:题中说,方差不会变小,所以稳定状态的方差一定是最大的。

稳定状态下会有\(a\&b = a\)或者\(a\&b = b\)即a,b中二进制集有包含关系。若将其从小到大排序,对于二进制集会有\(a_i \subseteq a_{i+1}\)。如此,对于每一个二进制来讲,前1~k全是0 k+1~n全是1。

具体做法就是,统计每个二进制位中1出现的次数,记为cnt[j]。从后往前扫一遍数组,枚举每个二进制位,若cnt[j]有剩余,就取出一个让该位置的数的第j位为1,否则为0.

注:代码中是相当于从大到小排序。

#include<algorithm>
#include<iostream>
using namespace std;
const int N = 1e5+10;
int n;
int A[N] , bcnt[15];
int main()
{
	unsigned long long Ex = 0 , Ex2 = 0 , tmp , res1 , res2;
	cin >> n;
	for(int i = 1 ; i <= n ; ++i)
	{
		cin >> A[i]; Ex += A[i];
		for(int j = 0 ; j < 15 ; ++j) if((A[i] >> j) & 1) bcnt[j]++;
	}
	for(int i = 1 ; i <= n ; ++i)
	{
		tmp = 0;
		for(int j = 0 ; j < 15 ; ++j) if(bcnt[j])
			tmp = tmp | (1 << j) , bcnt[j]--;
		Ex2 += tmp * tmp;
	}
	res1 = Ex2 * n - Ex * Ex;
	res2 = (unsigned long long)n * n;
	tmp = __gcd(res1 , res2);
	if(res1) cout << res1 / tmp << '/' << res2 / tmp << '\n'; else cout << "0/1" << '\n';
	return 0;
}

Jobs (Easy Version)

题意

有n个公司,每个公司提供\(m_i\)个岗位,每个岗位有三个限制条件IQ,EQ,AQ。只有自己的三个值都大于等于该岗位的限制,该公司才会发offer。现有Q个人问,每个人可以收到几个公司的offer。

数据范围

\(1<=n<=10,1<=m<1e5,1<=Q<=1e6,1<=IQ,EQ,AQ<=400\)

思路

建一个三维数组\(s[i][j][k]\)表示在这个三维前缀里有哪些公司会给offer,第i个公司用(1<<i)表示。

#include<iostream>
#include<random>
using namespace std;
const int mod = 998244353;
int s[401][401][401] , num[1 << 10];
int ksm(int a , int k)
{
	int ans = 1; a %= mod;
	for( ; k ; k >>= 1 , a = (long long)a * a % mod)
		if(k & 1) ans = (long long)ans * a % mod;
	return ans;
}
int main()
{
	int n , Q; scanf("%d%d" , &n , &Q);
	for(int i = 1 ; i <= n ; ++i)
	{
		int num , a , b , c; 
		scanf("%d" , &num);
		for(int j = 1 ; j <= num ; ++j)
		{
			scanf("%d%d%d" , &a , &b , &c);
			s[a][b][c] |= 1 << (i - 1);
		}
	}
	for(int i = 1 ; i < 400 ; ++i)
		for(int j = 1 ; j <= 400 ; ++j)
			for(int k = 1 ; k <= 400 ; ++k)
				s[i+1][j][k] |= s[i][j][k];
	for(int j = 1 ; j < 400 ; ++j)
		for(int i = 1 ; i <= 400 ; ++i)
			for(int k = 1 ; k <= 400 ; ++k)
				s[i][j+1][k] |= s[i][j][k];
	for(int k = 1 ; k < 400 ; ++k)
		for(int j = 1 ; j <= 400 ; ++j)
			for(int i = 1 ; i <= 400 ; ++i)
				s[i][j][k+1] |= s[i][j][k];
	int seed; scanf("%d" , &seed);
	for(int i = 1 ; i < (1 << 10) ; ++i) num[i] = num[i >> 1] + (i & 1);
	mt19937 rng(seed);
	uniform_int_distribution<> u(1,400);
	int lastans = 0 , res = ksm(seed , Q - 1) , inv = ksm(seed , mod - 2) , Ans = 0;
	for (int i=1;i<=Q;i++)
	{
	    int IQ=(u(rng)^lastans)%400+1;  // The IQ of the i-th friend
	    int EQ=(u(rng)^lastans)%400+1;  // The EQ of the i-th friend
	    int AQ=(u(rng)^lastans)%400+1;  // The AQ of the i-th friend
	    lastans = num[s[IQ][EQ][AQ]];
	    Ans = (Ans + (long long)lastans * res % mod) % mod; res = (long long)res * inv % mod;
	}
	printf("%d\n" , Ans);
	return 0;
}

标签:粒子,方差,int,蔚来,多校,long,牛客,include,mod
来源: https://www.cnblogs.com/R-Q-R-Q/p/16536572.html