闲话 11.2

也是打上搜了。


小木棍

曾经在题库上做过,数据水就过了,交洛谷发现只有 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:显然当前次数超过目前最优答案就不用再考虑了。

然后,

image

噗叽啪

🤔?。。。🤓!。。。🤫

  • R4:有没有什么一进去就知道这样做没前途的剪枝呢?诶,如果后面的瓜全加上都达不到目标重量显然是无解的,记录后缀和即可。

image

image

🧘👍

点击查看代码
#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\),这个我会🤓。

image

🤔?

考虑怎么入手这道题,首先比较明显的,我们必须保证 \(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 发毕业,爽🤤🤤🤤
不过连着两发镀彩是不是过于小概率了

偷偷塞一个干员数值


完结撒花~

上一个未完的是不是还在待续呢🤔

image

posted @ 2024-11-02 16:00  Ratio_Y  阅读(149)  评论(14编辑  收藏  举报