A. 相反数
Solution
签到题, 完全可以加大力度变成大数加法, 这里我直接贴了自己的大数加法模板
Code
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
const ll mod = 998244353;
const int DEG = 20;
const double PI = acos(-1.0);
const double eps = 1e-10;
const ll inf = 1e18;
const int N = 1e6 + 5;
static auto faster_iostream = []() {
std::ios::sync_with_stdio(false); // turn off sync
std::cin.tie(nullptr); // untie in/out streams
return 0;
}();
string add(string a, string b){
string c;
if(a.size() > b.size()) swap(a, b);
int len = min(a.size(), b.size());
int f = 0;
for(int i = len - 1, j = b.size() - 1; i >= 0; i--, j--){
c += ((a[i] - '0' + b[j] - '0' + f) % 10) + '0';
f = (a[i] - '0' + b[j] - '0' + f) / 10;
}
for(int j = b.size() - a.size() - 1; j >= 0; j--){
c += ((b[j] - '0' + f) % 10) + '0';
f = (b[j] - '0' + f) / 10;
}
if(f){
c += '1';
}
reverse(c.begin(), c.end());
return c;
}
int main(){
string s;
cin >> s;
string t = s;
reverse(t.begin(), t.end());
cout << add(t, s) << "\n";
return 0;
} B. Music Problem
Solution
提供一个假的做法, 数据强一点可能只能bitset
题意简化一下就是让我们在数组中找出一组子序列的和为3600的倍数
然后这是一道原题的缩减版 原题地址https://ac.nowcoder.com/acm/contest/91/L?&headNav=www
考虑动态规划:表示和在模3600意义下的子序列的个数
我们用一个数组记录目前为止和在模3600意义下为i的子序列的个数
有
时间复杂度, 直接搞会超时, 当dp[0] > 0 的时候直接跳出剪枝就行了
Code
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
const ll mod = 998244353;
const int DEG = 20;
const double PI = acos(-1.0);
const double eps = 1e-10;
const ll inf = 1e18;
const int N = 1e6 + 5;
static auto faster_iostream = []() {
std::ios::sync_with_stdio(false); // turn off sync
std::cin.tie(nullptr); // untie in/out streams
return 0;
}();
int a[N];
int dp[4000], temp[4000];
int main(){
int t;
cin >> t;
while(t--){
int n;
cin >> n;
ll sum = 0;
int flag = 0;
memset(dp, 0, sizeof(dp));
memset(temp, 0, sizeof(temp));
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i <= n; i++){
if(dp[0] > 0) break;
for(int j = 0; j < 3600; j++){
if(j == 0 || temp[j] != 0){
dp[(j + a[i]) % 3600] = temp[j] + 1;
}
if(dp[0] > 0) break;
}
for(int j = 0; j < 3600; j++){
temp[j] = max(temp[j], dp[j]);
}
}
if(dp[0] > 0){
cout << "YES\n";
}
else cout << "NO\n";
}
return 0;
} C. 完全平方数
Solution
签到题, 先打个表, 然后lower_bound() 查找一下下标
注意0也是完全平方数!
Code
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
const ll mod = 998244353;
const int DEG = 20;
const double PI = acos(-1.0);
const double eps = 1e-10;
const ll inf = 1e18;
const int N = 1e6 + 5;
static auto faster_iostream = []() {
std::ios::sync_with_stdio(false); // turn off sync
std::cin.tie(nullptr); // untie in/out streams
return 0;
}();
ll dp[N];
ll solve(ll x){
int pos = lower_bound(dp + 1, dp + 1 + 100000, x) - dp;
if(dp[pos] == x) return pos;
else return pos - 1;
}
int main(){
int q;
cin >> q;
for(ll i = 0; i <= 1e5; i++){
dp[i + 1] = i * i;
}
while(q--){
ll l, r;
cin >> l >> r;
if(l >= 1)
cout << solve(r) - solve(l - 1) << "\n";
else cout << solve(r) << "\n";
}
return 0;
} D. 小H和游戏
Solution
因为只需要查询城市距离为2的节点,
对于城市u, 我们考虑用一个fa数组找到城市的祖先fa[u], 它的祖先的祖先就是fa[fa[u]]
因为只需要考虑距离为2以内的节点, 那么只需考虑上述三个节点
开一个cnt[N][3]的数组,
cnt[i][0] 表示 i 点本身的影响
cnt[i][1] 表示 i 点儿子的影响
cnt[i][2] 表示 i 点儿子的儿子的影响
每次查询我们都直接更新cnt数组即可
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
const ll mod = 998244353;
const int DEG = 20;
const double PI = acos(-1.0);
const double eps = 1e-10;
const ll inf = 1e18;
const int N = 1e6 + 5;
static auto faster_iostream = []() {
std::ios::sync_with_stdio(false); // turn off sync
std::cin.tie(nullptr); // untie in/out streams
return 0;
}();
int tot, head[N];
struct Edge{
int v, nextz;
}edge[N << 1];
void addedge(int u, int v){
edge[tot].v = v;
edge[tot].nextz = head[u];
head[u] = tot++;
}
void init(){
tot = 0;
memset(head, -1, sizeof(head));
}
int fa[N];
void dfs(int u, int par){
fa[u] = par;
for(int i = head[u]; ~i; i = edge[i].nextz){
int v = edge[i].v;
if(v == par) continue;
dfs(v, u);
}
}
int cnt[N][3];
int main(){
init();
int n, m;
cin >> n >> m;
for(int i = 1; i <= n - 1; i++){
int u, v;
cin >> u >> v;
addedge(u, v);
addedge(v, u);
}
dfs(1, 0);
while(m--){
int u;
cin >> u;
cnt[u][1]++, cnt[u][2]++;
cnt[fa[u]][0]++, cnt[fa[u]][1]++;
cnt[fa[fa[u]]][0]++;
cout << cnt[u][0] + cnt[fa[u]][1] + cnt[fa[fa[u]]][2] << "\n";
}
return 0;
} E. 水题(water)
Solution
真·套娃题, 打个表我们发现f(i)其实就是个斐波那契数列, 然后我们只需要先判断x是不是斐波那契数
- 如果是的话, 对 m 做质因数分解统计贡献即可
对于求阶乘的尾0这类题
举个例子 求 13! 中 10进制下尾部0的个数
那么 因为 13! = 1 * 2 * ...... * 13;
考虑 10 的 质因子 2 和 5
其中 拥有质因子2的数字包括 2, 4, 6, 8, 10, 12
我们怎么求贡献呢?
我们发现 13 / 2 = 6 就是上面 6个数字的第一层贡献
6 / 2 = 3 就是第二层贡献(有的因子有两个2
3 / 2 = 1 就是第三层贡献
然后就没了, 总的贡献是 3 + 6 + 1 = 10
再考虑 质因子5的数字包括 5, 10
总的贡献是 13 / 5 = 2
两者取min, 得到13! 在10进制下有2个尾0
把这个结论推广到m进制 就是求m的质因子 再统计最小的贡献即可 - 不是的话就是个n皇后问题,模板贴一贴就好啦
Code
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long long LL;
const ll mod = 1e9 + 7;
const int DEG = 20;
const double PI = acos(-1.0);
const double eps = 1e-10;
const ll inf = 1e18;
const int N = 2e5 + 5;
static auto faster_iostream = []() {
std::ios::sync_with_stdio(false); // turn off sync
std::cin.tie(nullptr); // untie in/out streams
return 0;
}();
// 1 ^ 2 + 1 ^ 2 = 1 * 2
// 1 ^ 2 + 1 ^ 2 + 2 ^ 2 = 2 * 3
// 1 ^ 2 + 1 ^ 2 + 2 ^ 2 + 3 ^ 2 = 3 * 5
int a[20], q;
int ans = 0;
void dfs(int k){
if(k == q + 1) {
ans++; return ;
}
int flag = 0;
for(int i = 1; i <= q; i++){
a[k] = i; // 第k个皇后在i行
flag = 1;
for(int j = 1; j < k; j++){
if(a[j] == i || i - k == a[j] - j || i + k == a[j] + j){
flag = 0;
break;
}
}
if(flag){
dfs(k + 1);
}
}
}
ll F[100];
int main(){
ll x, m;
cin >> x >> m;
F[1] = F[2] = 1;
for(int i = 3; i <= 90; i++){
F[i] = F[i - 1] + F[i - 2];
//cout << F[i] << "\n";
}
int pos = -1;
for(int i = 3; i <= 90; i++){
if(F[i] == x){
pos = i;
break;
}
}
if(pos == -1){
q = x % min(13LL, m) + 1;
dfs(1); // n 皇后
cout << ans << "\n";
}
else {
vector<pair<int, int> > fac;
for(int i = 2; i * i <= m; i++){
if(m % i == 0){
int cnt = 0;
while(m % i == 0) m /= i, ++cnt;
fac.push_back({i, cnt});
}
}
ll ans = 4e18;
if(m > 1) fac.push_back({m, 1});
for(int i = 0; i < fac.size(); i++){
ll cur = x;
ll res = 0;
while(cur) res += cur / fac[i].first, cur /= fac[i].first;
ans = min(ans, res / fac[i].second);
}
cout << ans << "\n";
}
return 0;
} 
京公网安备 11010502036488号