1 条题解

  • 0
    @ 2025-8-24 22:29:40

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar green_orange
    Coding...

    搬运于2025-08-24 22:29:40,当前版本为作者最后更新于2021-03-07 14:39:48,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    USACO 2021 Feb T3 Count the Cows G

    分析

    首先转化题意,分析题中所给出的 x3k\lfloor\frac{x}{3^k}\rfloory3k\lfloor\frac{y}{3^k}\rfloor

    对于向下取整,我们所拥有的技巧相对较少,我们不妨将其写成如下形式:

    x=3ka+r0x = 3^ka + r_0 y=3kb+r1y = 3^kb + r_1

    其中 r0,r13k1r_0, r_1 \le 3^k - 1,那么我们所分析的条件可转化为 a,ba, b 之间的关系。

    接下来分析 a,ba, b 的性质

    我们观察到对于不同的 kk 值, a,ba, b 的系数始终是 33 的次幂,而题目中所给的关系中出现了对于 33 的余数,这启发我们将 a,ba,b 中再提出一个 33 来。那么有

    x=3k(3px+qx)+r0x = 3^k(3p_x + q_x) + r_0 y=3k(3py+qy)+r1y = 3^k(3p_y + q_y) + r_1

    题目中的关系可转化为 qxqy(mod2)q_x \equiv q_y \pmod{2}

    我们发掘出了对于单一的 kk 其具有的性质,考虑对于所有的 kk

    展开上式

    x=3k+1px+3kqx+r0x = 3^{k + 1}p_x + 3_{k}q_x + r_0 y=3k+1py+3kqy+r1y = 3^{k + 1}p_y + 3_{k}q_y + r_1

    我们发现有大量 33 的次幂,这启发我们尝试将 rr 也写成 33 的次幂相加的形式

    x=k=03kakx = \sum_{k = 0} 3^k a_{k} y=k=03kbky = \sum_{k = 0} 3^k b_{k}

    题目所给关系转化为 k,akbk(mod2)\forall k, a_k \equiv b_k \pmod{2}

    根据我们的经验,我们发现上式中的形式就是 x,yx, y 的三进制,要求转化为 x,yx, y 三进制下每一位关于 22 同余。

    这个结论对我们来说大有脾益,那么,我们就是求有多少的 d[d,d0]d \in [d, d_0] 满足 x0+dx_0 + dy0+dy_0 + d 三进制每一位下关于 22 同余。我们可以很容易联想到数位DP, 设状态为当前DP到多少位,x0+dx_0 + dy0+dy_0 + d 的更低位在做加法时有没有进位 ,由高位向低位DP即可,时间复杂度 O(qlogx)O(q\log x)

    实现

    #include <bits/stdc++.h>
    using namespace std;
    const static int mlg = 40;
    #define int long long
    int f[mlg][2][2][2];
    bool vis[mlg][2][2][2];
    int Ab[mlg], Bb[mlg], lb[mlg];
    bool check(int a, int b) {
    	if (a < 0 || b < 0 || a > 2 || b > 2)
    	  return false;
      else if ((a & 1) == (b & 1))
        return true;
      else
        return false;
    }
    typedef long long inte;
    inline int dfs(int p/*第几位*/, bool a/*x 是否进位*/, bool b/*y 是否进位*/, bool lim/*d 是否被顶满*/) {
    	if (p < 0)
    	  return (a == 0) && (b == 0);
    	if (vis[p][a][b][lim])
    	  return f[p][a][b][lim];
      vis[p][a][b][lim] = true;
    	inte ans = 0;
    	for (int v = 0; v <= (lim ? lb[p] : 2); ++v) {
    		for (int ak = 0; ak <= 1; ++ak) {
    			for (int bk = 0; bk <= 1; ++bk) {
    				if (check(Ab[p] - 3 * a + v + ak, Bb[p] - 3 * b + v + bk)) {
    					ans += dfs(p - 1, ak, bk, lim & (v == lb[p]));
    				}
    			}
    		}
    	}
    	return f[p][a][b][lim] = ans;
    }
    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
    	int Q;
    	cin >> Q;
    	while (Q--) {
    		inte x, y, d;
    		cin >> d >> x >> y;
    		memset(vis, 0, sizeof(vis));
    		for (int i = 0; i < mlg; ++i) {
    			Ab[i] = x % 3;
    			x /= 3;
    			Bb[i] = y % 3;
    			y /= 3;
    			lb[i] = d % 3;
    			d /= 3;
    		}
    		cout << dfs(mlg - 1, 0, 0, true) << endl;
    	}
      return 0;
    }
    
    • 1

    信息

    ID
    6541
    时间
    1000ms
    内存
    250MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者