codeforces #271E Three Horses 数论

题目大意:有一种卡片,正面和背面各写着一个整数,可以用一个有序数对(x,y)表示

有三种操作:

1.出示一张卡片(x,y),获得一张卡片(x+1,y+1)

2.出示一张卡片(x,y)(x,y都是偶数),获得一张卡片(x2,y2)

3.出示两张卡片(x,y)和(y,z),获得一张卡片(x,z)

一个人想要卡片(1,a1),(1,a2),(1,a3),...,(1,an),他可以携带一张初始卡片(x,y)(1≤x<y≤m),求有多少种方案

首先我们发现:

第一个操作不改变y?x的值

第二个操作可以使y?x变为原来的12

第三个操作可以使y?x变为原来的任意倍

那么我们不妨猜想:一张卡片(x,y)是否合法只与y?x的值有关

事实上这个是正确的

结论:卡片(x,y)满足条件当且仅当y?x是gcd(a1?1,a2?1,...,an?1)的一个约数d的2k倍

证明:

必要性:

不妨设y?x=d?2k(d为奇数),那么由上面的三个性质可知,所有能凑出的卡片的差值必为d的倍数

故如果d不是ai?1的约数,则一定无法凑出卡片(1,ai)

必要性得证

充分性:

不妨设y?x=d?2k(d为奇数且d|gcd(a1?1,a2?1,...,an?1))

我们任选一个k′,满足k′>=k且2k′≥x

那么首先我们利用(x,y)不断执行操作1和操作3得到(x,x+d?2k′)

然后我们利用操作1得到(2k′,(1+d)?2k′)

然后进行k′次操作2得到(1,1+d)

至此我们已经得到了(1,1+d),再不断进行操作1和操作3就能得到所有卡片了

证毕

然后就好办了,我们枚举gcd(a1?1,a2?1,...,an?1)的每个奇约数d,然后枚举d?2k,O(1)计算即可

时间复杂度O(d(ai)?logm)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 2020
using namespace std;
int n,m,gcd;
long long ans;
int divisor[M],tot;
void Get_Divisor(int n)
{
    int i;
    for(i=1;i*i<n;i++)
        if(n%i==0)
        {
            divisor[++tot]=i;
            divisor[++tot]=n/i;
        }
    if(i*i==n)
        divisor[++tot]=i;
}
int main()
{
    int i,j,x;
    cin>>n>>m;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&x);
        gcd=__gcd(gcd,x-1);
    }
    Get_Divisor(gcd);
    for(i=1;i<=tot;i++)
        if(divisor[i]&1)
            for(j=divisor[i];j<=m;j<<=1)
                ans+=m-j;
    cout<<ans<<endl;
    return 0;
}
时间: 2024-10-13 02:44:47

codeforces #271E Three Horses 数论的相关文章

Codeforces 413B Spyke Chatting(数论简单)

题目链接:Codeforces 413B Spyke Chatting 题目大意:n个人,m种聊天器,k次发送消息,然后给出n*m的矩阵,如果g[i][j]为1,则表示i号人会使用j号聊天器,接着给出k次消息发送者和聊天器,如果i在j种聊天器上发送了一条消息,那么所有使用j种聊天器的人都会接受到消息.现在要求每个人会接受到几条消息,自己发送的不算. 解题思路:分别记录每个聊天器上有多少个消息,以及每个人发送了多少条消息,然后计算每个人接受到多少条消息的时候只要将这个人所使用的各个聊天器消息数取和

[CodeForces - 1225C]p-binary 【数论】【二进制】

[CodeForces - 1225C]p-binary [数论][二进制] 题目描述 Time limit 2000 ms Memory limit 524288 kB Source Technocup 2020 - Elimination Round 2 Tags bitmasks brute force math *1600 Site https://codeforces.com/problemset/problem/1225/c 题面 Example Input1 24 0 Output

Codeforces 1034C Region Separation - 数论 - 动态规划

题目传送门 传送站I 传送站II 传送站III 题目大意 给定一个$n$个点的树$T = (G, V)$,每个点有一个正整数点权$a_{i}$.整棵树是第1级划分.定义第$i$级划分是将第$i - 1$级划分中的每个区域划分成至少两个新的区域,并且所有区域都是一个连通块,每个点在每一级中只属于一个区域,在同一级划分内每个区域内的点的点权和相等.一种划分方案包含它划分的每一级.两种划分方案不同当且仅当它们划分的级数不同,或者存在一个点在某一级中它们在两种划分方案中属于不同区域. 之前好像某次noi

Codeforces 762A k-th divisor(数论)

题目链接:k-th divisor 直接暴力-- 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define rep(i,a,b) for(int i(a); i <= (b); ++i) 6 #define LL long long 7 8 LL n, k, h, ans; 9 int num; 10 11 int main(){ 12 13 scanf("%lld%lld", &n, &a

Codeforces 622F 「数学数论」「数学规律」

题意: 给定n和k,求 1 ≤ n ≤ 109, 0 ≤ k ≤ 106 思路: 题目中给的提示是对于给定的k我们可以求出一个最高次为k+1的关于n的通项公式. 根据拉格郎日插值法,我们可以通过k+2个离散的点来确定这个通项.所以求出前k+2项,然后就可以确定公式. 拉格郎日差值法传送门:http://www.guokr.com/post/456777/ 最后得出的公式是酱紫的:(公式来自卿学姐博客) 然后问题来了,有除法如何搞定模运算...这个就用到逆元的运算了,逆元的定义就是大家都学过的离散

CodeForces 707C Pythagorean Triples (数论)

题意:给定一个数n,问你其他两边,能够组成直角三角形. 析:这是一个数论题. 如果 n 是奇数,那么那两边就是 (n*n-1)/2 和 (n*n+1)/2. 如果 n 是偶数,那么那两边就是 (n/2*n/2-1) 和 (n/2*n/2+1).那么剩下的就很简单了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #

Codeforces 17D Notepad 简单数论

由题意可知,anw =  (b-1)*b^(n-1)%c,则重点为求b^(n-1). 弱渣推不出来只能上公示. phi(c)为小于c且与c互质的个数. 当x >= phi(c)时:A^x = A(x%phi(c) + phi(c)) . 当x < phi(c)时:直接求即可. #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #includ

Codeforces 1016G Appropriate Team 数论 FWT

原文链接https://www.cnblogs.com/zhouzhendong/p/CF1016G.html 题目传送门 - CF1016G 题意 题解 今天太晚了,鸽一鸽,明天写. 代码 #include <bits/stdc++.h> using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef long double LD; namespace Pollard_Rho{ int pr

CodeForces 396A 数论 组合数学

题目:http://codeforces.com/contest/396/problem/A 好久没做数论的东西了,一个获取素数的预处理跟素因子分解写错了,哭瞎了,呵呵, 首先ai最大值为10^9,n为500,最坏的情况 m最大值为500个10^9相乘,肯定不能获取m了,首选每一个ai肯定是m的一个因子,然后能分解就把ai给分解素因子,这样全部的ai都分解了  就能得到m的 所有素因子 以及 所有素因子的个数,题目求的 是n个因子的 不同序列的个数,所以每次 只能选出n个因子,这n个因子由素因子