H:01背包,但是bit
这题一看数据范围很大,重量和价值都是1e8级别的,当时还在想是不是背包,原来就是位运算
具体来说,我们枚举m的每一位为1的1,强制这一位为0,这样m被分为前后两部分,对于前面的部分一定要满足或后小于m,简单说就是,在前面m不为1的位绝不能为1,而我们令当前这一位1为0了,对于后面所有位都为1,也不可能大于当前这一位,那么我们就可以根据这进行枚举计算了
int n, m;
int w[N], v[N];
void solve()
{cin >> n >> m;for (int i = 1; i <= n; i++)cin >> v[i] >> w[i];int ans = 0;for (int i = 1; i <= n; i++){if ((w[i] | m) == m)ans += v[i];}for (int i = 29; i >= 0; i--){if (m >> i & 1){int x = m ^ (1 << i); // 前面和m一样,但是第i位为0了,故后面就算全是1也不会大于m,就是对于后面解除了限制for (int j = i - 1; j >= 0; j--) // 后面没有限制{x |= (1 << j);}int res = 0;for (int j = 1; j <= n; j++)if ((w[j] | x) == x)res += v[j];ans = max(ans, res);}}cout << ans << endl;
}
I: It's bertrand paradox. Again!
找到两种方法会使得哪个统计量有显著区别,尝试区分这个统计量的均值;
比如求出法1该统计量均值m1、法2该统计量均值m2,那对于输入数据,直接看输入 数据的该统计量m和m1与m2谁更近就行了
其实很简单,就当再复习一遍随机数的求法了
void solve()
{// int ans1 = 0, ans2 = 0;// srand(time(NULL));// for (int i = 1; i <= 1e5; i++)// {// int x = rand() % 199 - 99;// int y = rand() % 199 - 99;// int r = rand() % 100 + 1;// while (x - r < -100 || x + r > 100 | y + r > 100 || y - r < -100)// {// r = rand() % 100 + 1;// }// ans1 += r;// }// for (int i = 1; i <= 1e5; i++)// {// int x = rand() % 199 - 99;// int y = rand() % 199 - 99;// int r = rand() % 100 + 1;// while (x - r < -100 || x + r > 100 | y + r > 100 || y - r < -100)// {// x = rand() % 199 - 99;// y = rand() % 199 - 99;// r = rand() % 100 + 1;// }// ans2 += r;// }// cout << LF(6);// cout << 1.0 * ans1 / 100000 << ' ' << 1.0 * ans2 / 100000 << endl;int n;double ans = 0;cin >> n;for (int i = 1; i <= n; i++){int x, y, z;cin >> x >> y >> z;ans += z;}ans = 1.0 * ans / 100000;double dis1 = abs(ans - 17);double dis2 = abs(ans - 25);if (dis1 < dis2)cout << "bit-noob" << endl;elsecout << "buaa-noob" << endl;
}
F:鸡数题!
第二类斯特林数
假设您已经学完了斯特林数,那本题的做法是:
• 将n个bit每个bit看作一件物品
• 将m个数字每个看作一个集合
• 注意到这几乎就是第二类斯特林数S(n,m)的定义:n个有区别球放到m个无区别盒子
• 还差在哪里呢?我们发现,本题的盒子(ai)并不是无区别的,但因为第二个条件要求了 每个盒子里的数从小到大有序,所以对于S(n,m)无序中的一种方案故只需要乘1即可,对其按ai大小排序就得 到了本题的一种方案,且可以证明这是一种一一映射(重点是证明没有多对一)
• 因此,本题答案就是斯特林数S(n,m)
百度链接第二类斯特林数
int pre[N];
int qpow(int a, int b)
{int res = 1;while (b){if (b & 1)res = res * a % mod;a = a * a % mod;b >>= 1;}return res;
}
void init()
{pre[0] = 1;for (int i = 1; i <= 1e6; i++){pre[i] = pre[i - 1] * i % mod;}
}
void solve()
{init();int n, m;cin >> n >> m;if (n < m){cout << 0;return;}int ans = 0;for (int i = 0; i <= m; i++){int t = 1;if (i % 2)t = -1;t *= pre[m] * qpow(pre[m - i], mod - 2) % mod * qpow(pre[i], mod - 2) % mod;t = (t * qpow(m - i, n) % mod) % mod;ans = ((ans + t) % mod + mod) % mod;}ans = (ans * qpow(pre[m], mod - 2) % mod) % mod;cout << ans << endl;
}