zoukankan      html  css  js  c++  java
  • 【裴蜀定理】【CF1091C】 New Year and the Sphere Transmission

    Description

    (n) 个人围成一个圈,按照顺时针从 (1)(n) 编号。第 (1) 个人会拿到一个球,他指定一个数字 (k),然后会将球传给他后面顺指针数第 (k) 个人。再次传到 (1) 后游戏结束。定义一次游戏的 (ans) 为所有拿到球的人的编号之和 ((1) 只算一次)。求所有可能的 (ans),按照升序输出,保证不超过 (10^5)

    Input

    一个整数 (n)

    Output

    一行多个整数,代表所有可能的 (ans)。按照是升序输出。

    Hint

    (1~leq~n~leq~10^9)

    Solution

    我们不妨将位置从 (0~sim~n-1) 编号。则一个位置 (p) 会在一次传球中被传到当且仅当 (p~equiv~xk~pmod n),其中 (x~in~Z^+)

    考虑上面的同余方程,他等价于 (xk~+~yn~=~p),其中 (x,y~in~Z^+)。根据裴蜀定理,这个方程有整数解当且仅当 (gcd(k,n) mid p)。考虑因为 (k~in~[1,n]),所以 (gcd(k,n)) 显然与 (n) 的因数一一对应。于是直接枚举 (n) 的因数 (s),则对答案产生贡献的只有 (0,s,2s,3s~dots~ts),其中 (t~=~frac{n}{s})。这是一个等差数列,直接使用等差数列求和公式可以 (O(1)) 计算答案。考虑我们位置是从 (0~sim~n-1) 编号的,所以每个位置的贡献都少算了 (1),总共少算了 (t),最后加上 (t) 即可。另外因为编号最大的位置 (ts) 事实上就是 (0) 号位置,我们对这个位置的贡献算了两遍,减掉第二遍计算的贡献 (n) 即可。

    Code

    #include <cmath>
    #include <cstdio>
    #include <set>
    #ifdef ONLINE_JUDGE
    #define freopen(a, b, c)
    #endif
    #define rg register
    #define ci const int
    #define cl const long long
    
    typedef long long int ll;
    
    namespace IPT {
    	const int L = 1000000;
    	char buf[L], *front=buf, *end=buf;
    	char GetChar() {
    		if (front == end) {
    			end = buf + fread(front = buf, 1, L, stdin);
    			if (front == end) return -1;
    		}
    		return *(front++);
    	}
    }
    
    template <typename T>
    inline void qr(T &x) {
    	rg char ch = IPT::GetChar(), lst = ' ';
    	while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
    	while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
    	if (lst == '-') x = -x;
    }
    
    template <typename T>
    inline void ReadDb(T &x) {
    	rg char ch = IPT::GetChar(), lst = ' ';
    	while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
    	while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
    	if (ch == '.') {
    		ch = IPT::GetChar();
    		double base = 1;
    		while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
    	}
    	if (lst == '-') x = -x;
    }
    
    namespace OPT {
    	char buf[120];
    }
    
    template <typename T>
    inline void qw(T x, const char aft, const bool pt) {
    	if (x < 0) {x = -x, putchar('-');}
    	rg int top=0;
    	do {OPT::buf[++top] = x % 10 + '0';} while (x /= 10);
    	while (top) putchar(OPT::buf[top--]);
    	if (pt) putchar(aft);
    }
    
    ll n;
    std::set<ll>ss;
    
    void work(cl);
    
    int main() {
    	freopen("1.in", "r", stdin);
    	qr(n);
    	for (rg int i = 1, sn = sqrt(n); i <= sn; ++i) if (!(n % i)) {
    		work(i);
    		work(n / i);
    	}
    	for (std::set<ll>::iterator it = ss.begin(); it != ss.end(); ++it) qw(*it, ' ', true);
    	putchar('
    ');
    	return 0;
    }
    
    void work(cl s) {
    	ll y = n / s;
    	ll ans = (((s + y * s) * y) >> 1) + y - n;
    	ss.insert(ans);
    }
    
  • 相关阅读:
    cocos代码研究(20)Widget子类LoadingBar学习笔记
    cocos代码研究(19)Widget子类ImageView学习笔记
    cocos代码研究(18)Widget子类Slider学习笔记
    cocos代码研究(17)Widget子类RadioButtonGroup学习笔记
    cocos代码研究(16)Widget子类RadioButton学习笔记
    cocos代码研究(15)Widget子类CheckBox学习笔记
    cocos代码研究(14)Widget子类Button学习笔记
    LeetCode:路径总和【112】
    LeetCode:平衡二叉树【110】
    LeetCode:二叉树的层次遍历||【107】
  • 原文地址:https://www.cnblogs.com/yifusuyi/p/10206825.html
Copyright © 2011-2022 走看看