也是打上搜了。
小木棍
曾经在题库上做过,数据水就过了,交洛谷发现只有 87pts。
《剪 枝 盛 宴》
- 钦定长度:最小肯定是最长的那根木棍,最长肯定是所有木棍的总和,并且这个长度一定只能是总和的因数。
- 选择顺序:如果选一个长的合法,那么选若干个和相同的短的一定合法但不优,因此按长度倒序排序。
- 如果合法立即回溯。
- 回溯后立即撤销标记,省略 memset。
- 每次拼接只会取长度不比上一次选择的木棍长的木棍,可以二分找。
- 如果某一根木棍不合法,与其长度相同的所有其他木棍均不合法。
- 如果某根小木棍与当前拼接刚好为钦定长度但不合法,此后一定不会出现合法方案,直接回溯。
点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(register int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(register int (x) = (y); (x) >= (z); (x)--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define lx ll
inline lx qr()
{char ch = getchar(); lx x = 0, f = 1;for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);return x * f;
}
#undef lx
#define qr qr()
#define fi first
#define se second
#define pii pair<int, int>
#define P_B(x) push_back(x)
#define M_P(x, y) make_pair(x, y)
const int Ratio = 0;
const int N = 100 + 5;
const int mod = 998244353;
int n, sum, ans;
int a[N];
bool yz[N], ok;
namespace Wisadel
{void Wdfs(int nlen, int nok, int ned, int id){if(nlen == ned){if(nok == sum / ned){ok = 1; return ;}fo(i, 1, n) if(!yz[i]){yz[i] = 1;Wdfs(a[i], nok + 1, ned, i);yz[i] = 0;if(ok) return ;break;}return ;}int l = id + 1, r = n;while(l < r){int mid = (l + r) >> 1;if(a[mid] <= ned - nlen) r = mid;else l = mid + 1;}int zc = 0;fo(i, l, n) if(!yz[i] && a[i] != zc){yz[i] = 1;Wdfs(nlen + a[i], nok, ned, i);yz[i] = 0;if(ok) return ;if(nlen + a[i] == ned) return ;zc = a[i];}}short main(){// freopen(".in", "r", stdin), freopen(".out", "w", stdout);n = qr;fo(i, 1, n) a[i] = qr, sum += a[i];ans = sum;sort(a + 1, a + 1 + n, [](int a, int b){return a > b;});fo(i, a[1], sum) if(sum % i == 0){yz[1] = 1;Wdfs(a[1], 1, i, 1);yz[1] = 0;if(ok){ans = i; break;}}printf("%d\n", ans);return Ratio;}
}
signed main(){return Wisadel::main();}
买瓜
💧
\(n\le 30\),一个瓜只有三种可能,暴力枚举 \(\mathcal{O(3^n)}\) 显然过不了,但是这是搜索题,所以重点还是在于各种小剪枝。
来!
- R1:和木棍同理,先拿重的比较优。
- R2:显然拿之后超过目标重量的不能拿。
- R3:显然当前次数超过目前最优答案就不用再考虑了。
然后,
噗叽啪
🤔?。。。🤓!。。。🤫
- R4:有没有什么一进去就知道这样做没前途的剪枝呢?诶,如果后面的瓜全加上都达不到目标重量显然是无解的,记录后缀和即可。
🧘👍
点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(register int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(register int (x) = (y); (x) >= (z); (x)--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define lx ll
inline lx qr()
{char ch = getchar(); lx x = 0, f = 1;for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);return x * f;
}
#undef lx
#define qr qr()
#define fi first
#define se second
#define pii pair<int, int>
#define P_B(x) push_back(x)
#define M_P(x, y) make_pair(x, y)
const int Ratio = 0;
const int N = 100 + 5;
const int mod = 998244353;
int n, m, ans = 1e9;
int a[N];
ll hz[N];
namespace Wisadel
{void Wdfs(int now, double tot, int tim){if(tim >= ans) return ;if(tot == 1.0 * m){ans = min(ans, tim);return ;}if(now > n || tot + 1.0 * hz[now] < 1.0 * m) return ;if(a[now] + tot <= 1.0 * m) Wdfs(now + 1, tot + 1.0 * a[now], tim);if((1.0 * a[now]) / 2 + tot <= 1.0 * m) Wdfs(now + 1, tot + (1.0 * a[now]) / 2, tim + 1);Wdfs(now + 1, tot, tim);}short main(){// freopen(".in", "r", stdin), freopen(".out", "w", stdout);n = qr, m = qr;fo(i, 1, n) a[i] = qr;sort(a + 1, a + 1 + n, [](int a, int b){return a > b;});fu(i, n, 1) hz[i] = hz[i + 1] + a[i];Wdfs(1, 0, 0);printf("%d\n", ans == 1e9 ? -1 : ans);return Ratio;}
}
signed main(){return Wisadel::main();}
Expression
诶,\(a+b=c\),这个我会🤓。
🤔?
考虑怎么入手这道题,首先比较明显的,我们必须保证 \(a+b=c\)。考虑逐位运算,从低到高,发现每一位上我们之多加一个数就一定能让该位运算合法,因此每一位还是只有三种可能。
考虑什么时候进位,显然,当 \(a+b\equiv c\pmod {10}\) 时这一位上合法,那么我们可以进位。
考虑什么时候结束,当 \(a=b=c=jinwei=0\) 时,即所有位都考虑完了,显然求解结束。
比较特殊一点,当 \(c=0\) 时,此时显然我们只需要在 \(c\) 上补充,单独考虑即可,本质上是一个小剪枝。
然后就做完了,温馨提示:直接这么写 scanf("%lld+%lld=%lld", &a, &b, &c)
就能很方便地快速输入,不需要用到 string 什么的。
点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(register int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(register int (x) = (y); (x) >= (z); (x)--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define lx ll
inline lx qr()
{char ch = getchar(); lx x = 0, f = 1;for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);return x * f;
}
#undef lx
#define qr qr()
#define fi first
#define se second
#define pii pair<int, int>
#define P_B(x) push_back(x)
#define M_P(x, y) make_pair(x, y)
const int Ratio = 0;
const int N = 100 + 5;
const int mod = 998244353;
ll a, b, c, ans = 1e9;
ll aaa, bbb, ccc;
namespace Wisadel
{void Wdfs(ll a, ll b, ll c, ll jin, ll aa, ll bb, ll cc, int now, ll bas){if(now >= ans) return ;if(!a && !b && !c && !jin){ans = now, aaa = aa, bbb = bb, ccc = cc;return ;}if(!c){ll res = a + b + jin;int zc = 0;while(res) zc++, res /= 10;Wdfs(0, 0, 0, 0, aa + bas * a, bb + bas * b, cc + bas * (a + b + jin), now + zc, bas * 10);return ;}if((a + b + jin) % 10 == c % 10){Wdfs(a / 10, b / 10, c / 10, (a % 10 + b % 10 + jin) / 10, aa + bas * (a % 10), bb + bas * (b % 10), cc + bas * (c % 10), now, bas * 10);return ;}Wdfs(a * 10 + (c % 10 - b % 10 - jin + 10) % 10, b, c, jin, aa, bb, cc, now + 1, bas);Wdfs(a, b * 10 + (c % 10 - a % 10 - jin + 10) % 10, c, jin, aa, bb, cc, now + 1, bas);Wdfs(a, b, c * 10 + (a % 10 + b % 10 + jin) % 10, jin, aa, bb, cc, now + 1, bas);}short main(){// freopen(".in", "r", stdin), freopen(".out", "w", stdout);scanf("%lld+%lld=%lld", &a, &b, &c);Wdfs(a, b, c, 0, 0, 0, 0, 0, 1);printf("%lld+%lld=%lld\n", aaa, bbb, ccc);return Ratio;}
}
signed main(){return Wisadel::main();}
锣鼓月赛 T3 打不动了,遂来写闲话抽卡记录。
体活,打了会羽毛球就回宿舍了,泡上面后开始打电话赛博抽卡。
Ratio:你看要是有火就是出了
我妈:诶这个好像就有火
😎😎😎
我妈:(一连串四星之后)这个是六星
Ratio:是不是六个字的
我妈:叫什么拉普兰德?
😋😋😋
Ratio:接着抽
我妈:这个又有火?🧐?怎么没六星
原来第一发是镀彩
Ratio:(科普了一下火和金)😬😬😬再来一发
我妈:诶这个又跟刚才一样
Ratio:😖😖😖那直接右上角跳过吧
我妈:那个“skip”是吧。。。诶有个六星
Ratio:!!!😆😆😆是不是金色头发的😋😋😋叫什么?
我妈:头发好像是浅白色的,等会我截图了,确实有点黄。。。
最后口述干员位置确认了就是忍冬,30 发毕业,爽🤤🤤🤤
未完待续
上一个未完的是不是还在待续呢🤔