B. Mask Allocation
题意
有(n cdot m)个口罩,现在问你怎样分配使得口罩既能全部平均分给(n)个医院,也能全部平均分配给(m)个医院。求出最少的盒子数,并且按照字典序大的结果输出
思路
比赛时想到一个画正方形的思路,盒子数即(n cdot m)的大矩形能由最少正方形组成,取正方形对应的边长的和
如图为样例5 4
,显然盒子数为(4 imes 1 + 1 imes 4 = 8)
然后观察发现这不就是每次都在当前区域取(lfloor m div n floor)个以(n)(假设m > n)为边长的正方形
余下的区域为(m \% n)$ imes n$,重复上述操作直到区域为0
可以用一个记忆划搜索来做,和gcd
有异曲同工之妙,
输出也是一个问题,但是没有关系(杰哥nb!!
),递归输出一遍即可
代码
/*************************************************************************
> FileName:
> Author: Lance
> Mail: lancelot_hcs@qq.com
> Date: 9102.1.8
> Description:
************************************************************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const double pi = acos(-1.0);
const double eps = 1e-6;
const int mod = 1e9 + 7;
#define debug(a) cout << "*" << a << "*" << endl
const int INF = 0x3f3f3f3f;//int2147483647//ll9e18//unsigned ll 1e19
const int maxn = 1000005;
//sacnf("%lf") printf("%f")
ll read() {
ll x = 0,f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
int t, n, m, flag;
int dp[10005][10005];
int dfs(int m, int n) {
if (n == 0) return 0;
if (dp[m][n]) return dp[m][n];
else return dp[m][n] = dfs(n, m % n) + m / n * n;
}
void print(int m, int n) {
if (n == 0) return;
int all = m / n * n;
for (int i = 0; i < all; i++)
if (flag == 0) {
printf("%d", n);
flag = 1;
} else printf(" %d", n);
print(n, m % n);
}
void solve() {
scanf("%d", &t);
while (t--) {
flag = 0;
n = read(), m = read();
if (m < n) swap(m, n);
ll s = m / n;
ll yu = m % n;
if (yu == 0) {
printf("%d
", m / n * n);
for (int i = 0; i < m; i++)
if (i == 0) printf("%d", n);
else printf(" %d", n);
puts("");
} else {
ll ans = dfs(m, n);
printf("%lld
", ans);
print(m, n);
puts("");
}
}
}
int main() {
// freopen("F:/Overflow/in.txt","r",stdin);
// ios::sync_with_stdio(false);
solve();
return 0;
}
H. Dividing
题意
给定n和k的取值范围,问有多少个合法的二元组,满足题目条件
思路
根据题目的意思,可以发现
当且仅当n = 1 或n为k的倍数或n - 1为k的倍数
时,(n, k)满足题目条件
- n = 1时,有N + K - 1个
然后分别讨论n为k的倍数和n - 1为k的倍数的情况
- n是k的倍数,(n=xcdot k),因为(n leq 10^{12}),那么可以减掉(x-1)个k,将n变为k,再/k为1
- n - 1为k的倍数,同理
计算步骤
(sum_{k=1}^{K} sum_{n=1}^{N}(n \% k=0|| n \% k=1) Rightarrow sum_{k=2}^{K} frac{n}{k}+sum_{k=2}^{K}left(frac{n-1}{k} ight) + K + N - 1)
然后解锁一个数论分块的知识盲区
面对这样一个问题
[sum_{i=1}^{n}leftlfloorfrac{n}{i} ight floor ]可以选择用O(n)的复杂度去暴力求解,但我们可以发现(ndiv i)的值在某一段中是相等的,比方说5/ 3, 5/ 4 ,5/5的大小都为1,所以可以用这一段的长度Len 乘以这一段的值就是可以快速求和。
int ans = 0; for(int l = 1, r = 0; l <= n; l = r + 1) { r = n / (n / l); // 求区间的右端,这是一个数学规律 ans += (r - l + 1) * (n / l); }
代码
/*************************************************************************
> FileName:
> Author: Lance
> Mail: lancelot_hcs@qq.com
> Date: 9102.1.8
> Description:
************************************************************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const double pi = acos(-1.0);
const double eps = 1e-6;
const int mod = 1e9 + 7;
#define debug(a) cout << "*" << a << "*" << endl
const int INF = 0x3f3f3f3f;//int2147483647//ll9e18//unsigned ll 1e19
const int maxn = 1000005;
//sacnf("%lf") printf("%f")
ll read()
{
ll x = 0,f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
ll t, n, N, K, ans = 0;
void solve()
{
N = read(), K = read();
// n是k的倍数 n=xk
for (ll i = 2, j; i <= K; i = j + 1) {
ll x = N / i;
if (x == 0) break;
j = N / x;
ans = (ans + ((min(j, K) - i + 1) % mod * (x % mod))) % mod;
}
// n-1是k的倍数 n=xk+1
for (ll i = 2, j; i <= K; i = j + 1) {
ll x = (N - 1) / i;
if (x == 0) break;
j = (N - 1) / x;
ans = (ans + ((min(j, K) - i + 1)) % mod * (x % mod)) % mod;
}
ans = (ans + N + K - 1) % mod;
cout << ans << '
';
}
int main()
{
// freopen("F:/Overflow/in.txt","r",stdin);
// ios::sync_with_stdio(false);
solve();
return 0;
}
J. Pointer Analysis
题意
四种赋值操作分别为,
- Uppercase = Uppercase
- Uppercase = Lowercase
- Uppercase. Lowercase = Uppercase
- Uppercase = Uppercase. Lowercase
给定n条赋值语句,可以通过任意顺序,次数来执行这些赋值语句,问每一个普通变量所能指向的最大对象集合
思路
理解了两种思路:
代码
/*************************************************************************
> FileName:
> Author: Lance
> Mail: lancelot_hcs@qq.com
> Date: 9102.1.8
> Description:
************************************************************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const double pi = acos(-1.0);
const double eps = 1e-6;
const int mod = 1e9 + 7;
#define debug(a) cout << "*" << a << "*" << endl
const int INF = 0x3f3f3f3f;//int2147483647//ll9e18//unsigned ll 1e19
const int maxn = 250;
//sacnf("%lf") printf("%f")
ll read()
{
ll x = 0,f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
int t, n;
struct node {
string s_1, equal, s_2;
}N[maxn];
struct SET {
set<char> S;
}SS[70];
set<char> amore[70][70];
inline bool check_low(char c) {
return c >= 'a' && c <= 'z';
}
void solve()
{
int n;
n = read();
for (int i = 0; i < n; i++) cin >> N[i].s_1 >> N[i].equal >> N[i].s_2;
for (int j = 0; j < n; j++) {
for (int i = 0; i < n; i++) {
int l1 = N[i].s_1.size(), l2 = N[i].s_2.size();
int tem_1 = N[i].s_1[0] - 'A', tem_2 = N[i].s_2[0] - 'A';
if (l1 == 1 && l2 == 1) {
if (check_low(N[i].s_2[0])) {
SS[tem_1].S.insert(N[i].s_2[0]);
} else {
for (auto it : SS[tem_2].S) {
SS[tem_1].S.insert(it);
}
}
} else { // cap.low
if (l1 == 3) {
int cap = N[i].s_1[0] - 'A', low = N[i].s_1[2] - 'a';
for (auto it_1 : SS[tem_1].S) {
for (auto it_2 : SS[tem_2].S) {
amore[it_1 - 'a'][low].insert(it_2);
}
}
} else {
int cap = N[i].s_2[0] - 'A', low = N[i].s_2[2] - 'a';
for (auto it_1 : SS[tem_2].S) {
for (auto it_2 : amore[it_1 - 'a'][low]) {
SS[tem_1].S.insert(it_2);
}
}
}
}
}
}
for (int i = 0; i < 26; i++) {
printf("%c: ", char(i + 'A'));
for (auto it : SS[i].S) cout << it;
puts("");
}
}
int main()
{
// freopen("F:/Overflow/in.txt","r",stdin);
// ios::sync_with_stdio(false);
solve();
return 0;
}
/*************************************************************************
> FileName:
> Author: Lance
> Mail: lancelot_hcs@qq.com
> Date: 9102.1.8
> Description:
************************************************************************/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const double pi = acos(-1.0);
const double eps = 1e-6;
const int mod = 1e9 + 7;
#define debug(a) cout << "*" << a << "*" << endl
const int INF = 0x3f3f3f3f;//int2147483647//ll9e18//unsigned ll 1e19
const int maxn = 250;
const int M = 26 + 26 * 26;
//sacnf("%lf") printf("%f")
ll read()
{
ll x = 0,f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
int t, n;
struct node {
string s_1, equal, s_2;
}N[maxn];
int f[M];
inline bool check_low(char c) {
return c >= 'a' && c <= 'z';
}
inline int turn(char c) {
if (check_low(c)) return c - 'a';
else if(c >= 'A' && c <= 'Z') return c - 'A';
}
int con1 = 0, con2 = 0, con3 = 0, con4 = 0;
void solve()
{
n = read();
for (int i = 0; i < n; i++) cin >> N[i].s_1 >> N[i].equal >> N[i].s_2;
for (int i = 0; i < 26 * M; i++) {
for (int j = 0; j < n; j++) {
int l1 = N[j].s_1.size(), l2 = N[j].s_2.size();
if (islower(N[j].s_2[0])) f[N[j].s_1[0]-'A'] |= 1 << (N[j].s_2[0] -'a'),con1++;
else if (l1 == 1 && l2 == 1) f[N[j].s_1[0] - 'A'] |= f[N[j].s_2[0] -'A'], con2++;
else if (l1 > l2)
for (int k = 0; k < 26; k++) {
if (f[N[j].s_1[0] - 'A'] >> k & 1)
f[26 + k * 26 + N[j].s_1[2] - 'a'] |= f[N[j].s_2[0] - 'A'], con3++;
}
else
for (int k = 0; k < 26; k++)
if (f[N[j].s_2[0] - 'A']>>k&1)
f[N[j].s_1[0] - 'A'] |= f[26 + k * 26 + N[j].s_2[2] -'a'];
}
}
for (int i = 0; i < 26; i++) {
printf("%c: ", char(i + 'A'));
for (int j = 0; j < 26; j++) if (f[i] >> j & 1) printf("%c", char('a' + j));
puts("");
}
}
int main()
{
// freopen("F:/Overflow/in.txt","r",stdin);
// ios::sync_with_stdio(false);
solve();
return 0;
}