小白月赛25
C白魔法师
题目链接https://ac.nowcoder.com/acm/problem/205862
知识点:图论、并查集
先将每个白色节点所对应的联通块中白色的个数进行预处理,dfs的过程中只有未访问还有子节点是白色才继续进行。(在这个过程中对res进行维护,因为有可能没有黑色节点不需要进行施法)
然后再将每个黑色节点中相连的白色联通块相加,再加上它本身施法变成白色来对res进行维护。
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
vector<int> adj[N];
int n;
char s[N];
int ans[N];
bool st[N];
vector<int> in;
void dfs(int u) {
in.push_back(u);
st[u] = true;
for(auto v : adj[u]) {
if(!st[v] && s[v] == 'W')
dfs(v);
}
}
int main()
{
scanf("%d", &n);
scanf("%s", s + 1);
for(int i = 1; i < n; i++) {
int a, b;
scanf("%d%d", &a, &b);
adj[a].push_back(b);
adj[b].push_back(a);
}
int res = 0;
for(int i = 1; i <= n; i++) {
if(!st[i] && s[i] == 'W') {
st[i] = true;
in.clear();
dfs(i);
int sum = in.size();
for(auto v : in)
ans[v] = sum; //将dfs中所有遍历过的点 都附上整个联通块的值
res = max(res, sum);
}
}
for(int i = 1; i <= n; i++) {
if(s[i] == 'B') {
int an = 1;
for(auto v : adj[i]) {
an += ans[v];
}
res = max(res, an);
}
}
printf("%d", res);
return 0;
}G解方程
题目链接:https://ac.nowcoder.com/acm/problem/205829
由于是单调递增的函数,因此可以进行二分。
用while(>eps)会TLE(r - l无限不动)解决方法是用long double或二分足够多的次数如1000次二分
#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
double a, b, c;
double f(double x) {
if(a == 1) return x + b * log(x);
else if(a == 2) return x * x + b * log(x);
else return x * x * x + b * log(x);
}
int main()
{
cin >> a >> b >> c;
double l = 1e-9, r = 1e9;
for(int i = 0; i <= 10000; i++) {
double mid = (l + r) / 2.0;
if(f(mid) <= c) l = mid;
else r = mid;
}
printf("%.8lf", l);
return 0;
}J异或和之和
知识点:位运算
思路:对没一位进行处理,在分别球每一位的贡献度
若该位有1则存在贡献度否则没有
三个数异或只有两种情况下该位是1
1 XOR 1 XOR 1
或
1 XOR 0 XOR 0
若该位有k个1则贡献度为
C(k,3)+C(k,1)*C(n - k, 2)
代码如下
#include<bits/stdc++.h>
using namespace std;
typedef long long ll; //由于a范围为1e18 是ll范围
const int mod = 1000000007;
const int N = 200010;
ll n;
ll t[64]; //用来存储每一位1的个数
ll qpow(ll a, ll b) {
ll res = 1;
while(b) {
if(b & 1) res = res * a % mod;
b >>= 1;
a = a * a % mod;
}
return res;
}
ll inv(ll x) { //求逆元
return qpow(x, mod - 2);
}
ll f(ll x, ll y) {
if(x < y) return 0;
ll res = 1;
for(ll i = 0; i < y; i++) {
res = res * (x - i) % mod;
res = res * inv(i + 1) % mod;
}
return res;
}
int main()
{
scanf("%lld", &n);
ll x;
for(ll i = 0; i < n; i++) {
scanf("%lld", &x);
ll j = 0;
while(x) {
if(x & 1) t[j]++;
j++, x >>= 1;
}
}
ll sum = 0;
for(int i = 0; i < 64; i++) {
sum += (1ll << i) % mod * (f(t[i], 3) + f(n - t[i], 2) * t[i] % mod) % mod;
sum %= mod;
}
printf("%lld", sum);
return 0;
}
查看3道真题和解析