B Mask Allocation
题意:
就是将 n ∗ m n∗m n∗m 个口罩分成 k k k 份,使得可以从中挑出 n n n 组,每组口罩数一样多;也可以从中挑出 m m m 组,每组口罩一样多,最后输出的字典序要最大。
AC代码:
const int N = 1e5 + 10;
const ll mod = 1e9 + 7;
int a[N];
int main()
{
int T;
sd(T);
while (T--)
{
int n, m;
sdd(n, m);
int cnt = 0;
while (n != 0 && m != 0)
{
if (n < m)
{
int t = n;
n = m;
m = t;
}
int tmp = m;
while (tmp--)
a[++cnt] = m;
n -= m;
}
pd(cnt);
rep(i, 1, cnt)
printf("%d%c", a[i], i == cnt ? '\n' : ' ');
}
return 0;
}
D Fake News
题意:
打表找规律,只有 1 1 1 和 24 24 24 第符合的。
AC代码:
int main()
{
int t;
sd(t);
while (t--)
{
sld(n);
if (n == 1||n==24)
puts("Fake news!");
else
puts("Nobody knows it better than me!");
}
}
H Dividing(数论分块)
题意:
用题给的三种操作,问 N , K N , K N,K 范围内有多少个不同二元组。
找找规律会发现对于每个
k
k
k ,
n
%
k
=
=
0
n\%k == 0
n%k==0 的所有点都可以凑到,因为这些点都是可以通过
(
1
,
k
)
(1,k)
(1,k) 进行
n
k
nk
nk 操作得到,
n
%
k
=
=
1
n\%k == 1
n%k==1也如此,因为这些点都是可以通过
(
1
,
k
)
(1,k)
(1,k) 进行
n
+
k
n+k
n+k 操作得到。
那么就每次累加
n
1
+
n
2
+
n
3
+
.
.
.
+
n
k
+
n
−
1
1
+
n
−
1
2
+
n
−
1
3
+
.
.
.
+
n
−
1
k
\frac{n}{1}+\frac{n}{2}+\frac{n}{3}+...+ \frac{n}{k}+\frac{n-1}{1}+\frac{n-1}{2}+\frac{n-1}{3}+...+ \frac{n-1}{k}
1n+2n+3n+...+kn+1n−1+2n−1+3n−1+...+kn−1 , 统计完去掉
k
=
1
k=1
k=1 时候重合的,加上除
k
>
=
2
k>=2
k>=2 时候每次漏的
1
1
1 即是答案。利用整数分块算法解答。
AC代码:
const int N = 2e7 + 50;
const int mod = 1e9 + 7;
ll n, k;
ll ans;
void cal(ll n, ll k)
{
for (ll l = 2, r; l <= k; l = r + 1)
{
r = n / l;
r = min(r, n);
if (r)
r = n / r;
else
r = k;
r = min(r, k);
int len = (r - l + 1) % mod;
int tmp = (n / l) % mod;
ans = (ans + len * 1ll * tmp % mod) % mod;
}
}
int main()
{
sldd(n, k);
ans = (n + k - 1) % mod;
cal(n, k);
n--;
cal(n, k);
pld(ans);
return 0;
}