2020年牛客暑期多校训练营(第七场)
2020年牛客暑期多校训练营(第七场)
D - Fake news
题意:输入一个数num,然后从1到num,将每个数的平方相加,判断得到的数是否为平方数。
实际上只有1与24满足题意
下面是没有发现只有1,24满足题意,暴力求解的代码
#include <cstdio> #include <cmath> typedef long long LL; const double eps = 1e-8; int main() { int n; scanf("%d", &n); while (n--) { LL num; LL sum = 0; scanf("%lld", &num); for (LL i = num; i > 0; i--) sum += i * i; if ((double)sqrt((double)sum) - (LL)sqrt((double)sum) < eps) printf("Fake news!\n"); else printf("Nobody knows it better than me!\n"); } return 0; }
显然会爆掉,这里可以使用平方和公式 计算最终结果,但是还是会爆掉,需要对表达式中
两两除以gcd, 然后对sum开根,观察结果是否为整数来判断sum是否为平方数;还可以
sum == (int)sqrt(sum) * (int)sqrt(sum)
判断sum是否为平方数
下面是AC的代码:
#include <cstdio> typedef long long LL; int main() { int n; scanf("%d", &n); while (n--) { LL num; scanf("%lld", &num); if (num == 1 || num == 24) printf("Fake news!\n"); else printf("Nobody knows it better than me!\n"); } return 0; }
H - Dividing
题意:定义了一种元组-Legend Tuple。输入N,K,当1 <= n <= N; 1 <= k <= K时,
- (1, k)始终是Legend Tuple
- (n, k)是Legend Tuple时,(n + k, k)也是Legend Tuple
- (n, k)是Legend Tuple时,(nk, k)也是Legend Tuple
所以当输入N,K后,计算有多少个Legend Tuple,由于数量可能会多,所以结果以的模为结果
思路:判断当前(n, k);从(1, k)到当前的(n, k),如果经历了第三种变换,那么当前的n一定是k的倍数;如果没有经历过第三种变换,n = xk + 1(x为整数),(n - 1)一定是k的倍数
#include <cstdio> #include <algorithm> using namespace std; typedef long long LL; const double epse = 1e-5; const int mod = 1e9 + 7; int main() { LL n, k; scanf("%lld%lld", &n, &k); LL cut = 0, ans = 0; //n是k的倍数 for (int i = 2; i <= k; i = cut + 1) { if (i > n) break; cut = min(n / (n / i), k); ans = (ans + (cut - i + 1) * (n / i)) % mod; } //n-1是k的倍数 for (int i = 2; i <= k; i = cut + 1) { LL ano_n = n - 1; if (i > ano_n) break; cut = min((ano_n) / (ano_n / i), k); ans = (ans + (cut - i + 1) * (ano_n / i)) % mod; } ans = (ans + k - 1) % mod; ans = (ans + n) % mod; printf("%lld\n", ans); return 0; }
B - Mask Allocation
题意:输入个口罩,然后将他们分组,分成的组数尽量最少。这些组中的一些组可以组合起来放在一个盒子里,盒子里可以有一个组,也可以有多个组。1.如果得到n个盒子,那么不论盒子里有多少组,但每个盒子里一定都是m个口罩;2.如果得到m个盒子,同样不论盒子里有多少组,每个盒子里一定都是n个口罩
思路:假设n < m(否则交换n,m),那么先得到n组,每组里有n个口罩;剩下的口罩有(m - n)n个,使用递归,也就是先判断(m - n)与n的大小关系,继续分组。递归结束的条件:口罩分完,
当需要分给n座医院时将剩余的组和之前的n组合放在一个盒子里,当需要分给m座医院时之前的n组不变,将剩余的组放在(m-n)个盒子里
#include <cstdio> #include <vector> #include <algorithm> using namespace std; vector <int> ans; //递归,结束条件为口罩分完,较小的数为零 void dfs(int n, int m) { if (m == 0) return ; for (int i = 0; i < (n / m) * m; i++) ans.push_back(m); dfs(max((n % m), m), min((n % m), m)); } int main() { int t; scanf("%d", &t); while(t--) { ans.clear(); int n; int m; scanf("%d%d", &n, &m); if (n < m) swap(n, m); dfs (n, m); //最小组数 printf("%d\n", ans.size()); for(int i = 0; i < ans.size(); i++) printf("%d ", ans[i]); } printf("\n"); return 0; }