牛客算法周周练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 }
View Code

 

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 }
View Code

 

 

 

posted @ 2020-06-26 19:52  好学生就是我  阅读(172)  评论(0编辑  收藏  举报