A find minimum operations
思路:将所给的n变成k进制数,答案就是n的k进制形式下的位数之和
代码:
#include <bits/stdc++.h>
using namespace std;typedef long long ll;ll n, k;void solve() {cin >> n >> k;ll cnt = 0;if(k == 1) cout << n << "\n";else {while(n) {cnt += n % k;n /= k;}cout << cnt << "\n";}
}int main() {int t;cin >> t;while(t -- ) solve();return 0;
}
B brightness begins
问题:
思路:
不难得到结论,只有当一个数的约数个数为偶数时,才可以保证灯处于on状态
模拟一组数据后发现,只有当该数为平方数时,约数个数才为偶数个
现在对于此结论给出证明:
将数x分解质因数可以得到以下形式:
由加法原理,乘法原理(其实就是排列组合)可知,x的约数个数与b有关
即约数个数
不难发现,只有当b全部为偶数时,n才为偶数,因为在乘法中只要有一个乘数为偶数,结果就是偶数
现在得到结论,b均为偶数
那么有
即可证明x为平方数
并且数n以内的平方数有个,因此就可以用二分求解答案
代码:
#include <bits/stdc++.h>
using namespace std;typedef long long ll;void solve() {ll k;cin >> k;auto find = [&](ll x) {ll l = 0, r = 1e9;while(l < r) {ll mid = l + r + 1 >> 1;if(mid * mid <= x) l = mid;else r = mid - 1;}return l;};//cout << find(3) << " ";ll l = 0, r = 2e18;while(l < r) {ll mid = l + r >> 1;if(mid - find(mid) >= k) r = mid;else l = mid + 1;}cout << l << "\n";
}int main() {int t;cin >> t;while(t -- ) solve();return 0;
}
C bitwise balenced
问题:
思路:首先观察式子,是否存在进位借位关系
注意到a | b >= a a & c <= a因此不存在借位关系,又因为是减法运算,所以也不会存在进位关系,那么这道题就是位独立的一道题,直接拆位讨论即可
#include <bits/stdc++.h>
using namespace std;typedef long long ll;
typedef unsigned long long ull;void solve() {ll b, c, d;ull a = 0;cin >> b >> c >> d;for(int i = 0; i <= 60; i ++ ) {int u = d >> i & 1;if(u == 1) {if((b >> i & 1) == 1 && (c >> i & 1) == 1) {a += 0;} else if((b >> i & 1) == 1 && (c >> i & 1) == 0) {a += 0;} else if((b >> i & 1) == 0 && (c >> i & 1) == 1) {cout << "-1\n";return;} else if((b >> i & 1) == 0 && (c >> i & 1) == 0) {a += ((ull)1 << i);}} else {if((b >> i & 1) == 1 && (c >> i & 1) == 1) {a += ((ull)1 << i);} else if((b >> i & 1) == 1 && (c >> i & 1) == 0) {cout << "-1\n";return;} else if((b >> i & 1) == 0 && (c >> i & 1) == 1) {a += 0;} else if((b >> i & 1) == 0 && (c >> i & 1) == 0) {a += 0;}}}cout << a << "\n";
}int main() {int t;cin >> t;while(t -- ) solve();return 0;
}
D connected dots
问题:
思路:首先注意到是联通块问题,因此可以考虑图论,并查集之类的做法,这里是并查集。
如果一个一个枚举判断是否在一个集合中,最差情况下要比较次,显然超时,这时候注意到我们的d很小,公差很小,就意味着每一个点最多与前面的d个点联通。我们可以用差分对一段线段打上标记,并强制点向前连边,那么我们就可以在d * n的时间复杂度内完成并查集的合并
代码:
#include <bits/stdc++.h>
using namespace std;typedef long long ll;
const int N = 2e5 + 10;int p[N], _size[N];void init(int n) {for(int i = 1; i <= n; i ++ ) {p[i] = i;_size[i] = 1;}
}int find(int x) {if(x != p[x]) {p[x] = find(p[x]);}return p[x];
}void merge(int a, int b) {int pa = find(a), pb = find(b);if(pa == pb) return;if(_size[pa] < _size[pb]) swap(pa, pb);_size[pa] += _size[pb];p[pb] = pa;
}void solve() {int n, m;cin >> n >> m;init(n);vector<vector<int>> diff((n + 11), vector<int>(11));while(m -- ) {int a, d, k;cin >> a >> d >> k;diff[a + d][d] ++;diff[a + d * k + d][d] --; }for(int i = 1; i <= 10; i ++ ) {for(int j = 1; j <= n; j ++ ) {diff[j][i] += diff[max(0, j - i)][i];}}for(int i = 1; i <= n; i ++ ) {for(int j = 1; j <= 10; j ++ ) {if(i - j >= 1) {if(diff[i][j]) {merge(i, i - j);}}}}set<int> se;for(int i = 1; i <= n; i ++ ) se.insert(find(i));cout << se.size() << "\n";
}int main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t;cin >> t;while(t -- ) solve();return 0;
}
E expected power
思路:注意到值域最大是1023,并且恰好二进制表示时各个位数都为1,由异或性质得知,最后S的值域也是不大于1023,可以枚举值域,然后用dp计算概率
时间复杂度1e8理论可以过,但是这里tle thinking....
代码:
#include <bits/stdc++.h>
using namespace std;typedef long long ll;
const ll mod = 1e9 + 7;ll qmi(ll a, ll b) {ll res = 1;while(b) {if(b & 1) (res *= a) %= mod;(a *= a) %= mod;b >>= 1;}return res;
}void solve() {ll n;cin >> n;vector<ll> a(n + 1), p(n + 1);for(int i = 1; i <= n; i ++ ) cin >> a[i];for(int i = 1; i <= n; i ++ ) {cin >> p[i];p[i] = (p[i] * qmi(10000ll, mod - 2)) % mod;}vector<vector<ll>> dp((n + 1), vector<ll>(1025));dp[0][0] = 1;for(int i = 1; i <= n; i ++ ) {for(ll val = 0; val <= 1023; val ++ ) {(dp[i][val ^ a[i]] += dp[i - 1][val] * p[i]) %= mod;(dp[i][val] += dp[i - 1][val] * (mod + 1 - p[i])) %= mod; }}ll ans = 0;for(int i = 0; i <= 1023; i ++ ) {(ans += dp[n][i] * i * i) %= mod;}cout << ans << "\n";
}int main() {ios::sync_with_stdio(false);cout.tie(0), cin.tie(0);int t;cin >> t;while(t -- ) solve();return 0;
}