首页 > 其他分享 >Gym102788,B - Rectangles题解

Gym102788,B - Rectangles题解

时间:2024-08-07 17:39:27浏览次数:17  
标签:std int 题解 back 4n 2n Rectangles primes Gym102788

水水水~
题目链接戳我

分析

首先根据题目条件可得式子=>\((x - 2)(y - 2) = n(2x + 2y - 4)\)
化简式子可得

\[\begin{align} (x - 2)(y - 2) = &n(2x + 2y - 4)\\ xy - 2x - 2y + 4 = &2nx + 2ny - 4n \\ x(y - 2n - 2) = &2ny - 4n - 4 + 2y \\ x = &\frac{2ny - 4n - 4 + 2y - 4n^2 + 4n^2 - 4n + 4n}{y - (2n + 2)} \\ x = &\frac{(2n + 2)(y - 2n - 2) + 4n^2 + 4n}{y - (2n + 2)} \\ x = &2n + 2 + \frac{4n^2 + 4n}{y - (2n + 2)} \end{align} \]

可以发现对于\(\frac{4n^2 + 4n}{y - (2n + 2)}\)这个式子想让其条件\((y - 2n - 2)|(4n^2 + 4n)\)成立,只能是\(y-(2n + 2)\)为\(4n^2 + 4n\)的因子,因此我们只需求出\(4n^2 + 4n\)的所有因子即可得到所有的(x, y)对。

具体实现

#include <bits/stdc++.h>

#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif

std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count());
namespace Factorizer {
    std::vector<int> primes;
    std::vector<int> least;
    void sieve(int n) {
        std::vector<int> nums;
        least.assign(n + 1, 0);
        for (int i = 2; i <= n; ++i) {
            if (least[i] == 0) {
                least[i] = i;
                nums.push_back(i);
            }
            int now = 0;
            while (now < (int)nums.size()
                && nums[now] <= least[i] && i * nums[now] <= n) {
                least[i * nums[now]] = nums[now];
                now += 1;
            }
        }
        primes = nums;
    }
    constexpr bool miller_rabin(long long n) {
        if (n <= 1 || (n != 2 && n % 2 == 0)) return false;
        for (auto a : {3, 5, 7, 11, 13, 17, 19, 23, 29}) {
            if (n % a == 0) return n == a;
        }
        if (n < 31 * 31) return true;
        long long d = n - 1;
        while (d % 2 == 0) d /= 2;
        constexpr long long bases[] = {
            2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37
        };
        for (long long a : bases) {
            if (n == a) return true;
            long long t = d;
            long long y = 1 % n;
            for (long long _t = t; _t != 0; _t >>= 1) {
                if (_t & 1) y = (__int128) y * a % n;
                a = (__int128) a * a % n;
            }
            while (t != n - 1 && y != 1 && y != n - 1) {
                y = (__int128) y * y % n;
                t <<= 1;
            }
            if (y != n - 1 && t % 2 == 0) return false;
        }
        return true;
    }
    long long pollard_rho(long long n) {
        if (n == 1 || miller_rabin(n)) return n;
        long long now = 0;
        do {
            long long t = std::gcd(++now, n), r = t;
            if (t != 1 && t != n) return t;
            long long g = 1;
            do {
                t = ((__int128) t * t % n + now) % n;
                r = ((__int128) r * r % n + now) % n;
                r = ((__int128) r * r % n + now) % n;
            } while ((g = std::gcd(abs(t - r), n)) == 1);
            if (g != n) return g;
        } while (now < n / now);
        return 0;
    }
    std::vector<long long> factor(long long n) {
        if (n == 1) return {};
        std::vector<long long> g, d;
        d.push_back(n);
        while (!d.empty()) {
            auto v = d.back();
            d.pop_back();
            auto rho = pollard_rho(v);
            if (rho == v) {
                g.push_back(rho);
            } else {
                d.push_back(rho);
                d.push_back(v / rho);
            }
        }
        std::sort(g.begin(), g.end());
        return g;
    }
}

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    #define int long long
    int n;
    std::cin >> n;  
    std::vector<int> primes = Factorizer::factor(4LL * n * n + 4LL * n);
    std::vector<std::pair<int, int>> fact;
    for (int i = 0; i < (int)size(primes); ++i) {
        int j = i + 1;
        while (j < (int)size(primes) && primes[i] == primes[j]) {
            j += 1;
        }
        fact.emplace_back(primes[i], j - i);
        i = j - 1;
    }
    std::vector<std::pair<int, int>> ans;
    auto power = [&](int a, int b) {
        int c = 1;
        for (; b; a *= a, b >>= 1)
            if (b & 1) c *= a;
        return c;
    };
    int num = 0;
    auto dfs = [&](auto &&self, int u, int f) {
        int y = f + (2 * n + 2), x = 2 * (n + 1) + 4 * n * (n + 1) / (y - 2 * n - 2);
        if (x > y) {
            std::swap(x, y);
        }
        ans.emplace_back(x, y);
        if (u == size(fact)) return ;
        auto [p, cnt] = fact[u];
        // debug(p, cnt);
        for (int i = 0; i <= cnt; ++i) {
            debug(u + 1, f * power(p, i));
            self(self, u + 1, f * power(p, i));
        }
    };
    dfs(dfs, 0, 1);
    std::sort(ans.begin(), ans.end());
    ans.erase(std::unique(ans.begin(), ans.end()), ans.end());
    std::cout << size(ans) << '\n';
    for (auto [x, y] : ans) {
        std::cout << x << ' ' << y << '\n';
    }
}

标签:std,int,题解,back,4n,2n,Rectangles,primes,Gym102788
From: https://www.cnblogs.com/sleeeeeping/p/18346919

相关文章

  • 题解:Codeforces Round 964 (Div. 4) D
    D.Slavic'sExamtimelimitpertest:2secondsmemorylimitpertest:256megabytesinput:standardinputoutput:standardoutputSlavichasaverytoughexamandneedsyourhelpinordertopassit.Hereisthequestionheisstrugglingwith:Ther......
  • 数列 题解
    题目id:1753题目描述给你一个长度为\(N\)的正整数序列,如果一个连续的子序列,子序列的和能够被K整除,那么就视此子序列合法,求原序列包括多少个合法的连续子序列?对于一个长度为\(8\)的序列,\(K=4\)的情况:\(2,1,2,1,1,2,1,2\)。它的答案为\(6\),子序列是位置\(1->\)位置\(8\),\(2->4\)......
  • 题解:Codeforces Round 964 (Div. 4) C
    C.Showeringtimelimitpertest:2secondsmemorylimitpertest:256megabytesinput:standardinputoutput:standardoutputAsacomputersciencestudent,Alexfacesahardchallenge —showering.Hetriestoshowerdaily,butdespitehisbestefforts......
  • CF1689C题解
    CF1689CInfectedTree题解怎么只有我这个蒟蒻不会DP啊。回归正题……简化题意给定一棵以$1$号节点为根的二叉树,总节点个数为$n$。现在$1$号节点感染了病毒,你在这一回合里可以使病毒所在节点的一个儿子不被感染,而病毒会感染一个不受保护的儿子。询问最多可以有多少不......
  • 烧烤 题解
    题目id:11063题目描述\(Snuke\)有一个烧烤聚会。聚会上,他将制作\(N\)份串烧。$\\\\\\\$一份串烧他有\(2N\)根烤肉钎子,它们都将用于制作串烧。第i个烤肉钎子的长度为Li。此外,他有无限供应的原料。他将原料串在两根烤肉钎子上做成一份串烧。一份串烧可串起的原料的最大......
  • 信创系统问题解决笔记
    本文记述解决信创系统显示问题过程经历,描述遇到的各种问题以及解决方法。问题描述测试反馈,在信创系统上,部分界面字体显示异常,表现为内容越界、文字区域显示为小空格,如下图所示:初步分析是字体原因,具体情况需要更进一步分析。问题复现测试团队的信创测试环境有UOS和Kylin两个......
  • CF1999题解
    题目链接CF1999A解题思路模拟。没了。参考代码/*Tips:你数组开小了吗?你MLE了吗?你觉得是贪心,是不是该想想dp?一个小时没调出来,是不是该考虑换题?打cf不要用umap!!!记住,rating是身外之物。该冲正解时冲正解!Problem:算法:思路:*/#include<bits/stdc++.h>usin......
  • 2024.8.7 模拟赛题解
    T1过于简单,不必阐述。T2给定一个仅包含\(A\)和\(P\)的字符串,每次操作可以删除相邻的\(AP\)或者\(PP\),问字符串最后的最小长度。$Sol:$为求最值问题,考虑贪心。先给出考场做法。发现若干的\(P\)是一定能合并掉的,于是贪心策略,就是如何最小化\(A\)的个数。对于每个......
  • 题解:Codeforces Round 964 (Div. 4) A
    A.A+BAgain?timelimitpertest:1secondmemorylimitpertest:256megabytesinput:standardinputoutput:standardoutputGivenatwo-digitpositiveinteger\(n\),findthesumofitsdigits.InputThefirstlinecontainsaninteger\(t\)(\(1......
  • 【题解】Solution Set - NOIP2024集训Day1 数据结构
    【题解】SolutionSet-NOIP2024集训Day1数据结构https://www.becoder.com.cn/contest/5429「CF1428F」FruitSequences线段树是可以维护区间最长子段的1。记固定右端点在\(i\),的答案为\(f_i\)。那么:\(a_i=0\),\(f_i=f_{i-1}\);\(a_i=1\),打一个单调栈维护所有的最长子......