牛客算法周周练10
A论如何出一道水题
题目描述:
给定 n,求一对整数 (i,j),在满足 1 ≤ i ≤ j ≤ n 且 在gcd(i,j)=1 的前提下,要求最大化 i+j 的值。
这是一道签到题,比较简单。在1到n的范围内,求i与j是互质,且i+j的值最大,由互质的性质,我们知道相邻的两个数肯定是互质的,它们之间除了1没有其他的约数了,所以就可以想到i可以等于n-1,j可以等于n,这样就可以了,但是还要注意当n等于1的情况。
1 #include <iostream> 2 #include <cstdio> 3 4 using namespace std; 5 typedef long long ll; 6 ll n; 7 8 int main() 9 { 10 scanf("%lld",&n); 11 if(n != 1) 12 printf("%lld",2*n-1); 13 else 14 printf("2"); 15 return 0; 16 }
B暴力出奇迹
题目描述:看题目链接里的题目;
我们将l到r的按位与的连续值看做a,l到r的连续和看成b,也就是说我们要求l到r使得最大化a*b,因为最大化与他们两个都有关并且在同一个区间内求它们,所以我们就不能先找到一个最大值再来确定另一个,我们需要将它们全部遍历一遍。因为对按位与的限制更大,所以与运算的规则,全1才为1,可以想象将数字转化为二进制,我们一位一位的找,比如在右边的第一位,我们可以看是否有连续的第一位都是1,这样就可以将它们的和 和 乘积储存起来,然后取其中的最大值,最后输出最大值,如果有一位是0,那就说明不可以将这个数字放进这个序列中,所以将这个数字抛弃,转移到下一个数字。这题的解题思路大概就是这样,详细看代码。
1 #include <bits/stdc++.h> 2 #include <iostream> 3 #include <cstdio> 4 5 using namespace std; 6 const int ma = 1e5 + 10; 7 typedef long long ll; 8 ll n,ans,num[ma]; 9 10 int main() 11 { 12 scanf("%lld",&n); 13 for(int i = 1; i <= n; i++) 14 scanf("%lld",num+i); 15 ll sum,pro; 16 for(int i = 0; i <= 22; i++) 17 { 18 sum = 0 ,pro = num[1];//sum要重新赋值为0,pro要赋值为num[1]这样才不会有影响 19 for(int j = 1; j <= n; j++) 20 { 21 if((num[j]>>i)&1)//右移运算,将num[j]右移i位,并判断第i位是不是1 22 { 23 sum += num[j],pro &= num[j]; 24 ans = max(ans,sum*pro); 25 } 26 else 27 { 28 sum = 0,pro = num[j+1]; 29 } 30 } 31 } 32 printf("%lld",ans); 33 return 0; 34 }