A
給出x,y兩個數,花費a元可以同時加1或減1,花費b元可以單個數加1或減1
貪心:將兩個數變到同樣大小,再一起減到0更優,注意特判2a和b的關係
int main()
{
int t; scanf("%d", &t);
while (t--) {
ll x, y, a, b; scanf("%lld%lld%lld%lld", &x, &y, &a, &b);
if (x < y) swap(x, y);
if (b > 2 * a) b = 2 * a;
printf("%lld\n", a * x + (b - a) * y);
}
}
B
給出t串,求t爲s的子序列的滿足最小循環節的s串
可以得出,可以構造的s串的最小循環節只有1或者2,特判t串的循環節是否爲1
const int maxn = 1e2 + 5;
char s[maxn << 1], t[maxn];
int main()
{
int T; scanf("%d", &T);
while (T--) {
scanf("%s", &t);
int n = strlen(t);
int cnt0 = 0, cnt1 = 0;
for (int i = 0; i < n; ++i) {
if (t[i] == '0') cnt0++;
else cnt1++;
}
if (cnt0 == 0 || cnt1 == 0) {
puts(t);
continue;
}
int flg = 0;
for (int i = 0; i < n; ++i) {
if (t[i] == '0') {
if (flg == 0) flg = 1;
else if (flg == 1) {
printf("01");
}
}
else if (t[i] == '1') {
if (flg == 0) {
printf("01");
}
else if (flg == 1) {
printf("01");
flg = 0;
}
}
}
if (flg != 0) printf("01");
printf("\n");
}
}
C
給出a和b,求給出區間之間滿足
可以知道可以求出0~r之間滿足的數 與 0~l-1之間的數做差得出答案
推了很久,最後打表給出0~max(a,b)-1的數不滿足,max(a,b)~LCM(a,b)的數滿足。
看了別人的推導,滿足的數爲,即暴力求出0~lcm之間的情況即可
ll a, b;
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int main()
{
int t; scanf("%d", &t);
while (t--) {
int q; scanf("%lld%lld%d", &a, &b, &q);
if (a > b) swap(a, b);
int gap = a * b / gcd(a, b), incre = gap - b;
while (q--) {
ll l, r; scanf("%lld%lld", &l, &r); r++;
ll rsum = r / gap * incre + (r % gap > b ? r % gap - b : 0);
ll lsum = l / gap * incre + (l % gap > b ? l % gap - b : 0);
printf("%lld ", rsum - lsum);
}
printf("\n");
}
}
D
給出n個物品,每個物品大小爲,大小範圍爲k,給出每個揹包的現在表示大小超過i的數必須
因爲給出滿足單調遞減,可以從大到小貪心選元素,每個揹包能放就放
const int maxn = 2e5 + 5;
int cnt[maxn], c[maxn];
vector< vector<int> > res(1);
int main()
{
int n, k; scanf("%d%d", &n, &k);
for (int i = 1; i <= n; ++i) {
int x; scanf("%d", &x);
cnt[x]++;
}
for (int i = 1; i <= k; ++i) scanf("%d", &c[i]);
int pre = 0, ans = 0;
for (int i = k; i; --i) {
int now = 0;
if (i != k && c[i] == c[i + 1]) now = pre;
while (cnt[i]) {
if (now == ans) {
++ans;
res.emplace_back();
continue;
}
if (res[now].size() < c[i]) {
res[now].emplace_back(i);
--cnt[i];
}
else ++now;
}
pre = now;
}
printf("%d\n", ans);
for (int i = 0; i < ans; ++i) {
printf("%d", res[i].size());
for (auto j : res[i]) printf(" %d", j);
printf("\n");
}
}
E
將“車”放在nxn的棋盤上,使每個格子都要被覆蓋(車可以覆蓋一排和一列的格子),且互相攻擊的車爲k個
要覆蓋所有格子,就每行或每列都存在車,畫圖可知,題意即求將n個元素放在n-k個集合中方案數。行列情況對稱,則答案爲
代入第二類斯特靈公式求解
onst int maxn = 2e5 + 5;
const ll mod = 998244353;
ll fib[maxn];
ll qpow(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1) res = 1ll * res * a % mod;
b >>= 1;
a = 1ll * a * a % mod;
}
return res;
}
ll c(int n, int m) {
return 1ll * fib[n] * qpow(1ll * fib[m] * fib[n - m] % mod, mod - 2) % mod;
}
int main()
{
fib[0] = 1;
for (int i = 1; i < maxn; ++i) fib[i] = 1ll * fib[i - 1] * i % mod;
ll n, k; scanf("%lld%lld", &n, &k);
if (k == 0) printf("%lld\n", fib[n]);
else if (k >= n) printf("0\n");
else {
int K = n - k;
ll ans = 0;
for (int i = 0; i <= K; ++i) {
ans = (1ll * qpow(mod - 1, i) * c(K, i) % mod * qpow(K - i, n) % mod + ans) % mod;
}
ans = 2ll * c(n, K) * ans % mod;
printf("%lld\n", ans);
}
}