[题解]第十一届北航程序设计竞赛预赛——D.最大公约数

题目描述

给一个长度为n(1<=n<=100000)的正整数列,分成尽量多的非空段,使得每一段的最大公约数相等。一个数的最大公约数是它本身。

解题思路

要求每一段子列的gcd相等,不妨设为d,可以知道d是所有数的最大公约数,即d=(a[1],a[2],……,a[n])。于是我们先求出d,然后从前往后扫描,记st=1,移动ed,计算d1=(a[st],……,s[ed]),直到d1==d,得到的区间[st,ed]就是一个符合题目要求的子列;记st=ed+1,重复上述操作,直至数列扫完。算法时间复杂度为O(n logx),其中x表示数列的数的大小。

注:

1、由于gcd(a[i],……,a[j])=gcd(gcd(a[i],……,a[k]),gcd(a[k+1],……,a[j])),(i<k<j),所以计算多个数的gcd直接两两计算即可;计算子列的gcd直接在扫描时每多一个书就多一次求gcd即可。

2、按照上述算法可能出现最后一段的gcd不等于d的情况,可以看作最后一段不被单独分出来,而是跟前一段合并为一段的。注意到跟前面的一段合并后gcd一定等于d,因为d=(a[1],a[2],……,a[n]),最后一段的gcd记为ds只能是d的倍数,而前一段的gcd为d,所以合并后gcd一定为d。另外,所谓“前一段”是一定存在的,否则所有的最大公约数不可能为d。

附:c++代码

 1 #include <iostream>
 2 #include <cstdio>
 3
 4 using namespace std;
 5 #define MaxN 100020
 6
 7 int a[MaxN];
 8
 9 inline void Get_int(int &Ret)
10 {
11     char ch;
12     bool flag=false;
13     for(;ch=getchar(),ch<‘0‘||ch>‘9‘;)
14         if(ch==‘-‘)
15             flag=true;
16     for(Ret=ch-‘0‘;ch=getchar(),ch>=‘0‘&&ch<=‘9‘;Ret=Ret*10+ch-‘0‘);
17     flag&&(Ret=-Ret);
18 }
19
20 inline int My_gcd(int a, int b)
21 {
22     int r;
23     if(a < b)
24         swap(a, b);
25     while(b)
26     {
27         r = a % b;
28         a = b;
29         b = r;
30     }
31     return a;
32 }
33
34 int main ()
35 {
36     int n, ans;
37     int x, tmp;
38     int i;
39     bool flag;
40     while(scanf("%d", &n) != EOF)
41     {
42         for(i = 1; i <= n; i++)
43         {
44             Get_int(a[i]);
45             if(i == 1)
46                 x = a[i];
47             else
48                 x = My_gcd(a[i], x);
49         }
50         if(n == 1)
51         {
52             printf("1\n");
53             continue;
54         }
55         //printf("%d\n", x);
56         ans = 0;
57         flag = false;
58         for(i = 1; i <= n; i++)
59         {
60             if(!flag)
61             {
62                 if(a[i] == x)
63                     ans++;
64                 else
65                 {
66                     tmp = a[i];
67                     flag = true;
68                 }
69             }
70             else
71             {
72                 tmp = My_gcd(a[i], tmp);
73                 if(tmp == x)
74                 {
75                     flag = false;
76                     ans++;
77                 }
78             }
79         }
80         printf("%d\n", ans);
81     }
82     return 0;
83 }

另一种思路

这是官方给出的题解,动归

最大公约数满足结合律,所以题目所说相等的gcd就是原数列的gcd,不妨设为d。

设f[i]为前i个数能分的最大段数,枚举最后一个段是[j+1,i],则有gcdik=j+1ak=d,而f[i]=maxf[j]+1。如果j不存在,可以认为f[i]是不合法的部分,令f[i]=0即可。

不难证明满足条件的j是一段前缀区间,而且f[i]是单调的,所以最大的f[j]一定是尽量靠右的,可以直接找到这个j来对f[i]更新答案。

区间gcd可以预处理ST表得到,或者顺着推以每个点结尾的区间gcd即可,可以证明以每个点结尾的区间gcd的值个数是不超过logn个的,所以整体的复杂度是O(n(logn)^2)。

时间: 2024-10-06 03:27:42

[题解]第十一届北航程序设计竞赛预赛——D.最大公约数的相关文章

[题解]第十一届北航程序设计竞赛预赛——I.神奇宝贝大师

题目描述 一张n*m的地图,每个格子里面有一定数量的神奇宝贝,求一个最优位置,使得所有神奇宝贝到该位置的曼哈顿距离最小. 一共有T组数据,每组数据包含两行,第一行是n和m(1<=n,m<=2000),第二行是三个整数x,y,q,表示处于(i,j)(1<=i<=n,1<=j<=m)的神奇宝贝的数量为((x^i) + (y^j))mod q,其中1<=x,y<=2000,1<=q<=10. 输出最小的曼哈顿距离和. 解题思路 这道题与2015编程之美

[题解]第十一届北航程序设计竞赛预赛——H.高中数学题

题目描述 解题思路 可以求得通项公式:an = 2n + 1,所以问题就变成等差数列求异或和,这个具体为什么对我还不能很好地解释清楚,先挖坑吧. 附:c++代码 1 #include <iostream> 2 #include <cstdio> 3 4 using namespace std; 5 6 typedef unsigned long long llt; 7 8 llt Cal(llt x, llt d, llt P, llt Num) 9 { 10 llt ret =

[题解]第十一届北航程序设计竞赛预赛——A.模式

题目描述 输入一个学号,判断是计算机系or软件学院or其他院系. 解题思路 水题,直接判断or除以10000都可以.不废话,直接上代码. 1 #include <iostream> 2 #include <cstdio> 3 4 using namespace std; 5 6 int main() 7 { 8 char s[20]; 9 while(scanf("%s", s) != EOF) 10 { 11 if(s[2] == '0' &&

湖南省第十一届大学生程序设计竞赛:Internet of Lights and Switches(HASH+二分+异或前缀和)

Internet of Lights and Switches Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 3  Solved: 3[Submit][Status][Web Board] Description You are a fan of "Internet of Things"(IoT, 物联网), so you build a nice Internet of Lights and Switches in your huge

河南省第十一届ACM程序设计竞赛 修路

Problem C: 修路 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 63  Solved: 22[Submit][Status][Web Board] Description SNJ位于HB省西部一片群峰耸立的高大山地,横亘于A江.B水之间,方圆数千平方公里,相传上古的神医在此搭架上山采药而得名.景区山峰均在海拔3000米以上,堪称"华中屋脊".SNJ是以秀绿的亚高山自然风光,多样的动植物种,人与自然和谐共存为主题的森林生态区. S

“亚信科技杯”南邮第七届大学生程序设计竞赛之网络预赛 (部分题解)

“亚信科技杯”南邮第七届大学生程序设计竞赛之网络预赛 F 自动售货机 时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte总提交 : 60            测试通过 : 13  题目描述 教学楼有一台奇怪的自动售货机,它只售卖一种饮料,单价5元,并且只收5元.10元面值的货币,但是同学们都很喜欢喝.这个售货机里没有多余的找零,也就是说如果一个持有10元的同学第一个购买,则他不能获得5元找零,但是如果在他之前有一个持有5

POJ 3420 Quad Tiling 题解 《挑战程序设计竞赛》

POJ 3420 Quad Tiling贴瓷砖:4*N的地板上用2*1的瓷砖铺满,求所有方案数对M求余.3.4熟练掌握动态规划矩阵的幂久违地上了节课,太无聊,只好刷一题.假设S[n]表示填满n时的方案数,有S[0]=1.定义矩阵M[p][q] := 边缘p和边缘q可以拼合时取1,否则取0所谓的可以拼合表示,两个边缘拼起来后长度为1(为2就拼接不起来了),且内部缝隙可以用2*1的瓷砖填满.那么M就有一些简单的性质了,比如M的第一行应该是:0 0 0 0 0 0... 继续阅读:码农场 » POJ

POJ 3411 Paid Roads 题解 《挑战程序设计竞赛》

POJ 3411 Paid Roads开路:N个城市间有m条单向路,分别从a到b,可以在c处交P路费,也可以直接交R路费.那么问题来了,你的挖掘机怎么开最省钱?3.4熟练掌握动态规划状态压缩DP乍一看可以Dijkstra,实际上的确可以Dijkstra.不过多了一个预交费的c,所以在遍历的时候多了一维状态,这个维度储存当前走过的城市集合.在Dijkstra的时候,如果走过了c那么就有两个选择,选其中最省的即可:否则没得选.#include <iostream> #include&nb.

《ACM国际大学生程序设计竞赛题解Ⅰ》——基础编程题

这个专栏开始介绍一些<ACM国际大学生程序设计竞赛题解>上的竞赛题目,读者可以配合zju的在线测评系统提交代码(今天zoj貌似崩了). 其实看书名也能看出来这本书的思路,就是一本题解书,简单暴力的通过题目的堆叠来提升解决编程问题的能力. 那么下面开始探索吧. zoj1037: BackgroundFor years, computer scientists have been trying to find efficient solutions to different computing p