先声明,这场我爆0了一题都没做出来。
B题
链接:https://ac.nowcoder.com/acm/contest/13504/B
来源:牛客网
题目描述
母牛哥在电脑面前坐久了,想站起来看看窗外的小山坡,于是就想出了这个问题:
给定一个大小为n的数组a,序号从1开始,
计算:
max{ R - L | 1 <= L <= R <= n, a[L] == a[R], 对于所有i (L <= i <= R), 满足a[i] >= a[L] }.
也就是找到两个坐标,这两个坐标的值相等,并且他们之间的值都大于等于这两个坐标上的值.
这两个坐标相减最大能是多少.
输入描述:
第一行一个整数n,第二行n个整数
输出描述:
输出题目所求的值
示例1
输入
5 1 2 3 2 1
输出
4
说明
当L=1,R=5时,满足题目条件的最优解,答案为R-L=5-1=4
备注:
数据范围:
1<=n<=1e6
0<=a[i]<=1e9
题解:
栈。
建一个栈,当出现比栈顶小的数时,一路往回退,退到小于或等于它的数。
因为大于它的数,绝对不会在后面找相同的数组成区间,已经不满足条件了,所以可以直接去掉。
往回找,找到小于或等于它的数。
如果小于它,则表示它仍可以被纳入一个区间里。
如果等于它,则代表已经可以组成一个两边相等中间全比它大的区间了,就计算。
但是要注意像 1 2 2 2 1 3 3 1 这样的数据,当你第二个1往回找到第一个1的时候,不要将第二个1入栈,因为第三个1可以和第一个1组成一个更长的区间,这一点需要注意。
代码:
#include<iostream>
#include<stack>
using namespace std;
int n,a[1000006],ans;
stack<int> s;
int main()
{
ios::sync_with_stdio(false),cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
s.push(1);
for(int i=2;i<=n;i++)
{
while(!s.empty() && a[s.top()]>a[i])
s.pop();
bool f=false;
if(!s.empty() && a[s.top()]==a[i])
{
ans=max(ans,i-s.top());
f=true;
}
if(!f)
s.push(i);
}
cout<<ans;
return 0;
}
C题
链接:https://ac.nowcoder.com/acm/contest/13504/C
来源:牛客网
题目描述
母牛哥有一桶油漆,把它用完可以给n平方米的墙涂上颜色.
母牛哥想要在墙上涂5个正方形(这些正方形的边长都是整数,单位是米),并且刚好把油漆用完.
母牛哥能做到吗?
输入描述:
第一行一个数字t(<=1000),表示测试样例数量
接下来t行,每行一个数字n(0<=n<=1000000),表示母牛哥的油漆可以涂多少平方米.
输出描述:
输出t行,对于每个输入.
如果母牛哥能够做到,就输出YES.
否则输出NO.
示例1
输入
2 4 55
输出
NO YES
说明
4显然不能分解成5个正平方数,所以这桶油漆不能涂5个正方形.
55可以涂5个正方形,他们面积分别是1 4 9 16 25.
题解:
其实,只是为了做题的话,先打个表,暴力算算那些不合适,然后直接特判即可。
具体证明为什么除那些数外都可以由5个平方数组成大家有兴趣可以上网查阅资料。
#include<iostream>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int a;
cin>>a;
if(a<5 || a==6 || a==7 || a==9 || a==10 || a==12 || a==15 || a==18 || a==33)
cout<<"NO\n";
else
cout<<"YES\n";
}
return 0;
}
E题
链接:https://ac.nowcoder.com/acm/contest/13504/E
来源:牛客网
题目描述
小明来到一片海滩上,他很喜欢捡贝壳,但他只喜欢质量为x的倍数的贝壳。
贝壳被排列成一条直线,下标从1到n编号,小明打算从编号为区间[l,r]\left [l,r \right ][l,r]的贝壳中,捡起所有他喜欢的贝壳。你能帮他计算出他能捡多少贝壳吗。
给出一个大小为n(n≤105)n(n\le10^5)n(n≤105)的数组,下标从1到n编号,a1,a2,...ana_1,a_2,...a_na1,a2,...an(ai≤105)(a_i \le 10^5)(ai≤105))表示贝壳的质量。
给出q(q≤5∗104)q(q\le5*10^4)q(q≤5∗104)次询问,每次询问包含3个整数l,r,x(1≤l≤r≤n,1≤x≤105)l,r,x(1\le l \le r\le n,1\le x\le 10^5)l,r,x(1≤l≤r≤n,1≤x≤105),对于每次询问,输出一行整数,表示这次询问中能捡到的贝壳数。
输入描述:
第一行给出两个整数n和q,含义如上所示。
第二行给出n个整数表示a1,a2,...ana_1,a_2,...a_na1,a2,...an
接下来q行,每行3个整数l,r,x,含义如上所示
输出描述:
对于每次询问输出该次询问中能捡到的贝壳数
示例1
输入
5 3 1 2 3 4 5 1 3 2 1 5 3 2 5 4
输出
1 1 1
示例2
输入
10 3 5532 24380 19363 11022 23965 22383 27049 22357 30453 7451 1 6 2 3 10 10 1 10 9
输出
3 0 1
题解:
实话讲,我不太会算这题的时间复杂度。
这一题,用vector去保留同一个质量的贝壳在的编号,然后暴力去找就行了。
也挺暴力的。
可以考虑用二分优化一下。
#include<iostream>
#include<stdio.h>
#include<vector>
using namespace std;
int n,q,Max;
int a[100005];
vector<int> v[100005];
void read_in()
{
ios::sync_with_stdio(false),cin.tie(0);
cin>>n>>q;
for(int i=1;i<=n;i++)
{
cin>>a[i];
v[a[i]].push_back(i);
Max=max(Max,a[i]);
}
}
int main()
{
read_in();
while(q--)
{
int l,r,x,ans=0;
cin>>l>>r>>x;
for(int k=x;k<=Max;k+=x)
for(int i=0;i<v[k].size();i++)
if(v[k][i]>=l && v[k][i]<=r)
ans++;
cout<<ans<<endl;
}
return 0;
}
I题
链接:https://ac.nowcoder.com/acm/contest/13504/I
来源:牛客网
题目描述
众所周知,一个序列拥有许多非空子序列。
所谓子序列就是在原序列中任意删除 0 个或多个元素,然后保持剩下元素的顺序不变所形成的序列。非空子序列集意味着剩下的子序列不能为空。
比如对于序列[1, 2, 3],它的所有非空子序列为:[1, 2, 3],[1, 2],[1, 3],[2, 3],[1],[2],[3]。再比如序列 [1, 1],它的非空子序列有:[1, 1],[1] (删除了第一个 1),[1] (删除了第二个1) 。
现在母牛哥手里有一个长度为 n 的正整数序列,他现在要为这个序列的所有非空子序列打分。对于一个序列而言,它的评分标准为序列里所有数的乘积(只有一个数的序列,分数就是这个数)。
母牛哥想要知道所有分数的和,但由于结果太大了,所以你只要告诉母牛哥结果对 1000000007 取模即可。
输入描述:
第一行为 n,表示这个序列长度为 n (1 <= n <= 10^6)。
接下来的一行有 n 个数字 a1, a2, …… , an (1 <= ai <= 2 * 10^9) 表示序列的 n 个数字。
输出描述:
一个非负整数,表示结果对 1000000007 取模。
示例1
输入
3 1 2 3
输出
23
示例2
输入
2 1 1
输出
3
题解:
这题,用到一个规律,集合的所有子集元素乘积之和。
这个就是 的所有子集元素乘积之和。
但是这题注意的是取模的时候,(a%p - b%p )%p 的时候一定要 +p,即为(a%p - b%p + p)%p。
因为a%p 之后 可能会小于b%p 所以相减得到一个小数。
一定要记住!!!!!!!
代码:
#include<iostream>
#include<stdio.h>
using namespace std;
int n;
long long ans=1,ot;
long long oo=1000000007;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
long long a;
scanf("%lld",&a);
ans= (ans%oo * (a+1)%oo )%oo;
}
ot=(ans%oo-1)%oo;
ot=ot%oo;
printf("%lld",ot);
return 0;
}