目录
A.你也喜欢数学吗编辑
E.动物朋友
F.松鼠排序
G.Reverse
J.合唱比赛
K.以撒和隐藏房间
L.中位数
A.你也喜欢数学吗
输入描述
第一行一个正整数k(1<=k<=1e12)
输出描述
输出一行一个整数表示答案
示例1
输入
1
输出
1
示例2
输入
3
输出
10
思路
是等于,将整个式子再化简得到,然后用(__int)防止数据溢出。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll n;
signed main()
{
cin>>n;
ll ans=(((__int128)n*(n+1))*(n+2))/6%mod;
cout<<ans;
return 0;
}
E.动物朋友
题目描述
已知有n个动物朋友排成一排,每个动物朋友都有一个正整数的快乐值,涛涛每次会和连续的动物朋友玩,并且获得这些动物朋友快乐值的和的快乐,而涛涛是个完美主义者,他觉得快乐值刚好是m时候才是快乐的,现在请问有多少种选择方式,使得所选的连续的动物朋友的快乐值刚好为m。
输入描述
第一行输入n(1<=n<=1e6)和m(1<=m<=1e6)。
第二行输入n个正整数,第i个代表第i个动物朋友的快乐值。(1<=ai<=1e5)
输出描述
一个整数,表示可能存在的选法数量,如果没有,就输出0;
输入1
1 5
4
输出1
0
输入2
11 45
1 4 1 9 19 8 10 8 1 2 3
输出2
1
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
int n,m;
int a[N];
int s[N];
int cnt;
signed main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];
s[i]=s[i-1]+a[i];
}
for(int i=1;i<=n;i++)
{
int l=i,r=n;
while(l<r)
{
int mid=l+r>>1;
if(s[mid]-s[i-1]>=m) r=mid;
else l=mid+1;
}
if(s[r]-s[i-1]==m) cnt++;
}
cout<<cnt;
}
F.松鼠排序
题目描述
松鼠宝宝有一排n个大小不一的坚果,松鼠宝宝想把坚果从小到大排序,每次他会选择两个坚果a和b每次花费1点力气把这两个坚果交换,爱动脑筋的松鼠宝宝想知道他排完这n个坚果一共需要花费的最少力气是多少?
输入描述
第一行一个整数n代表坚果数
接下来一行n个整数代表每个坚果的大小(每个坚果大小都不一样,即大小为1-n的一个排列)1<=n<=1e5坚果大小x,1<=x<=n。
输出描述
一行输出代表松鼠宝宝花费的最小力气。
输入
3
3 2 1
输出
1
思路
模拟交换。
#include <bits/stdc++.h>
using namespace std;
int a[100005];
int main()
{
int n,i,k;
cin>>n;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(i=1;i<=n;i++)
{
while(a[i]!=i)
{
swap(a[a[i]],a[i]);
k++;
}
}
cout<<k;
}
G.Reverse
题目描述
给定一个长度为n的01串,你需要选择一段任意长度(可以为0)的区间对其翻转,翻转后,求最长的一段连续的全是1的区间的长度。
输入描述
输入共2行。
第一行一个整数n(1≤n≤10^6)。
第二行一个长度为n的01序列。
输出描述
输出一个整数,表示最长的长度。
示例1
输入
10
0111001011
输出
5
说明
翻转区间[5,10],翻转为0111110100。
思路
排序后最长连续1的长度。如果有超过两个连续1,那么就是最长的+第二长的。
#include<bits/stdc++.h>
using namespace std;
int n;
string s;
int main()
{
cin>>n>>s;
vector<int>v;
int cnt=0;
for(auto it:s)
if(it=='1') cnt++;
else v.push_back(cnt),cnt=0;
if(cnt!=0) v.push_back(cnt);
sort(v.begin(), v.end());
int k = v.size();
if(k>1) cout<<v[k-1]+v[k-2];
else if(k==1) cout<<v[k-1];
else cout<<0;
return 0;
}
J.合唱比赛
题目描述
河南农业大学信管学院举办一年一度的合唱比赛,目前你是评委之一,剩下还有其他的n位评委,给定一个正整数n和n个正整数表示这n个评委给目前在表演的团队的分数,评分规则为在所有评委(包括你)的分数中去掉一个最高分和最低分,剩下的取平均值(总共n-1个值),现在你可以参与评分(1~100之间的整数),问最终结果会在什么区间内,用两个数表示这个区间,结果保留6位小数。
输入描述
第一行给定一个正整数n
接下来一行给定n个整数表示n个评委的分数
2<=n<=1000
输出描述
输出两个保留六位的小数l,r表示答案。
示例1
输入
3
80 90 100
输出
85.000000 95.000000
示例2
输入
4
3 5 9 13
输出
5.666667 9.000000
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n;
double a[N];
signed main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
double l=0,r=0;
for(int i=1;i<=n;i++)
{
if(i!=1) r+=a[i];
if(i!=n) l+=a[i];
}
printf("%.6lf %.6lf",l/(n-1),r/(n-1));
return 0;
}
K.以撒和隐藏房间
题目描述
你说得对,但是以撒的结合是一款集合了推箱子、血统检验、少女换装、宠物养成等等元素的地牢探险/Rougelike类跨世代大作。游戏发生在以撒和他的妈妈住的小房子的[地下室]里,在这里,天真的以撒受[教条]的影响,进入了一场幻想中的地下室冒险。你将扮演以撒扮演的圣经中的人物,在充满怪物和杂物的地下室里获取各种激起回忆的道具,靠败们击败天使或是恶魔的阻挡,找回缺失的亲情——同时,逐步发掘[父母离异]的真相。
以撒又一次的逃进了地下室
地下室可以看作一个n*m的矩阵的迷宫,其中有些格子是有门相连房间,有些则是无法通过的墙壁。以撒发现其中一些墙壁似乎是空心的,可以通过爆炸打开隐藏的房间,而隐藏房的生成有一定的规律,以撒认为一个墙壁格子在满足以下所有情况时可能会是隐藏房间:
1, 该墙壁格子和三个普通房间相邻
2, 在满足1条件的情况下,不能和boss房间相邻
但是以撒正在和萌死戳交战,
现在你需要编写程序告诉他是否存在可能是隐藏房间的格子。
如果存在,输出两行,第一行是一个YES,第二行输出可能为隐藏房间的格子的数量
如果不存在,输出NO
输入描述
第一行两个整数n,m(3<m,n<=1000)
然后是一个n*m矩阵,表示地图状态,0表示墙壁,1表示房间,2表示boss房间
输出描述
如果存在,输出两行,第一行是一个YES,第二行输出可能为隐藏房间的格子的数量
如果不存在,输出NO
示例1
输入
3 3
001
110
211
输出
YES
1
示例2
输入
3 4
0010
1111
0102
输出
NO
备注:
隐藏房间不属于房间
思路
搜索。
#include<bits/stdc++.h>
using namespace std;
const int N=1100;
int n,m,ans;
char g[N][N];
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
void solve()
{
cin>>n>>m;
for(int i=0;i<n;i++) cin>>g[i];
bool f=false;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(g[i][j]!='0') continue;
bool flag=true;
int cnt=0;
for(int k=0;k<4;k++)
{
int l=i+dx[k],r=j+dy[k];
if(l>=0&&l<n&&r>=0&&r<m)
if(g[l][r]=='1') cnt++;
else if(g[l][r]=='2')
{
flag=false;
break;
}
}
if(flag&&cnt==3)
{
f=true;
ans++;
}
}
if(f) cout<<"YES"<<endl<<ans;
else cout<<"NO"<<endl;
}
signed main()
{
solve();
return 0;
}
L.中位数
题目描述
某天cbyyx突发奇想给lyt出了一道题:给定序列a,b,保证|a|+|b|为奇数且小于1e6,给定q组询问,每次将a序列其中一个数修改或将b序列其中一个数修改,问每次操作后两序列合并后的中位数是多少,lyt觉得这个问题太简单并把它秒了,但lyt觉得这个题对新生来说有点困难,于是他简化问题如下:给定两个正整数n,m,再给定长度为n的正整数序列a, 保证n为奇数。接下来m行,每行两个正整数p, x。表示把a[p]修改为x。对于每次操作输出修改后的中位数。
输入描述
第一行输入两个正整数n,m
第二行给定n个正整数表示序列a1~an
接下来m行每行给定两个数p,x,表示将a[p]修改为x。
1<=n<=1e6,1<=m<=1e5,1<=x<=1e6
输出描述
对于每次操作输出每次操作后序列的中位数的值。
示例1
输入
7 3
1 2 3 4 5 6 7
2 3
4 4
7 1
输出
4
4
3
思路
树状数组求有序序列第k个数。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10;
int a[N], tr[N];
int n, m;
int lowbit(int x)
{
return x & -x;
}
void add(int x, int v)
{
for (int i = x; i <= N; i += lowbit(i)) tr[i] += v;
}
int query(int x)
{
int res = 0;
for (int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
signed main()
{
cin>>n>>m;
for (int i = 1; i <= n; i++)
{
cin>>a[i];
add(a[i],1);
}
int k=(n+1)/2;
while (m--)
{
int p,x;
cin>>p>>x;
add(a[p],-1);
a[p]=x;
add(x,1);
int l=1,r=N;
while(l<r)
{
int mid=l+r>>1;
if(query(mid)>=k) r=mid;
else l=mid+1;
}
cout<<l<<endl;
}
return 0;
}