比赛网址

​https://vjudge.net/contest/350953​

首先:因为ACM寒假欢乐赛 题解_前缀和突然去世,导致体验极差,等ACM寒假欢乐赛 题解_前缀和活过来就可以看到提交结果了(这谁想得到呢,昨天还是活的)

ACM寒假欢乐赛 题解_#include_03

A.1228

原题链接:

​https://codeforces.com/problemset/problem/1228/A​

题意:

给定一个区间ACM寒假欢乐赛 题解_i++_04),让你取区间中任意一个数ACM寒假欢乐赛 题解_#include_05,要求ACM寒假欢乐赛 题解_#include_05的每一位数字都不相同,不存在这样的数则输出ACM寒假欢乐赛 题解_#include_07

思路:

暴力判断即可。

标程:

#include <bits/stdc++.h>
using namespace std;
int main() {
int l, r;
scanf("%d%d", &l, &r);
for (int i = l; i <= r; ++i) {
int book[15] = {0}, temp = i, flag = 0;
while (temp) {
book[temp % 10]++;
if (book[temp % 10] == 2) {
flag = 1;
break;
}
temp /= 10;
}
if (!flag)
return !printf("%d\n", i);
}
return !printf("-1\n");
}

B.1118

原题链接:

​https://codeforces.com/contest/1118/problem/B​

题意:

ACM寒假欢乐赛 题解_#include_08个数,问依次删去一个数后,剩下的数的奇数位置上的和和偶数位置上的和相等的有多少个。

思路:

是对于删除第ACM寒假欢乐赛 题解_#include_09位数的话,第ACM寒假欢乐赛 题解_#include_09位之前的奇偶性是不变的,第ACM寒假欢乐赛 题解_#include_09位之后的奇偶性是和原来相反的,所以我们用前缀和,分别求出奇数位置上的前缀和和偶数位置上的前缀和,然后对于第ACM寒假欢乐赛 题解_#include_09位删除掉了以后就是判断一下前ACM寒假欢乐赛 题解_前缀和_13位的奇数前缀和加上后面偶数位的前缀和是否等于前ACM寒假欢乐赛 题解_前缀和_13位的偶数前缀和加上后面奇数位置的前缀和。

标程:

#include <bits/stdc++.h>
#define
using namespace std;
const int N = 2e5 + 10;
int a[N], odd[N], even[N];
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
odd[1] = a[1];
even[1] = 0;
for (int i = 2; i <= n; i++) {
if (i & 1) {
odd[i] = a[i] + odd[i - 1];
even[i] = even[i - 1];
} else {
odd[i] = odd[i - 1];
even[i] = even[i - 1] + a[i];
}
}
int ans = 0;
for (int i = 1; i <= n; i++) {
if (odd[i - 1] + even[n] - even[i] == even[i - 1] + odd[n] - odd[i]) {
ans++;
}
}
printf("%d\n", ans);
return 0;
}

C.1559

原题链接:

​http://acm.hdu.edu.cn/showproblem.php?pid=1559​

题意:

给你一个ACM寒假欢乐赛 题解_#include_15的整数矩阵,在上面找一个ACM寒假欢乐赛 题解_前缀和_16的子矩阵,使子矩阵中所有元素的和最大。

思路;

预处理二维前缀和然后ACM寒假欢乐赛 题解_#include_17查询就行了。

标程:

#include <bits/stdc++.h>
#define
using namespace std;
const int N = 1e3 + 5;
const int inf = 0x3f3f3f3f;
ll a[N][N];
int main() {
int t, m, n, x, y;
ll ans;
scanf("%d", &t);
while (t--) {
ans = -inf;
scanf("%d%d%d%d", &n, &m, &x, &y);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
scanf("%lld", &a[i][j]);
a[i][j] = a[i][j] + a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1];
}
}
//从i,j开始 到 i+x-1,j+y-1
for (int i = 1; i <= m - x + 1; i++) {
for (int j = 1; j <= n - y + 1; j++) {
ans = max(ans, a[i + x - 1][j + y - 1] - a[i + x - 1][j - 1] - a[i - 1][j + y - 1] + a[i - 1][j - 1]);
}
}
printf("%lld\n", ans);
}
return 0;
}

D.2456

原题链接:

​http://poj.org/problem?id=2456​

题意:

ACM寒假欢乐赛 题解_#include_08个地方,有ACM寒假欢乐赛 题解_i++_19头牛,一头牛只能分配一个地方,问如何分配使得所有牛之间的距离最小的那个值最大,是多少。

思路:

求最小值的最大值,先对隔间的位置进行排序,隔间之间的最小值最大为最后那个隔间的位置减去第一个隔间的位置,这样的话我们就可以二分了,判断每俩头牛之间最小相距ACM寒假欢乐赛 题解_前缀和_20距离时,能否装下ACM寒假欢乐赛 题解_i++_21头牛,如何判断也是一个值得注意的地方,肯定要把第一个隔间的位置放一头牛,贪心的思想,然后判断下一个隔间的位置与上一个放牛的位置的距离是否大于等于ACM寒假欢乐赛 题解_前缀和_20,符合条件则放入,并把上一个放牛的位置改为当前位置。

标程:

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int a[N];
int n,m;
int judge(int x) {
int num=1;
int pos=a[1];
for(int i=2; i<=n; i++) {
if(a[i]-pos>=x) {
num++;
pos=a[i];
}
}
return num>=m;
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++) {
scanf("%d",&a[i]);
}
sort(a+1,a+1+n);
int l=0,r=1e9;
int ans;
while(l<=r) {
int mid=(l+r)/2;
if(judge(mid)) {
l=mid+1;
ans=mid;
} else {
r=mid-1;
}
}
printf("%d\n",ans);
return 0;
}

E.1988

原题链接:

​http://poj.org/problem?id=1988​

题意:

给定ACM寒假欢乐赛 题解_前缀和_23个方块,排成一行,将它们编号ACM寒假欢乐赛 题解_i++_24ACM寒假欢乐赛 题解_前缀和_23。再给出ACM寒假欢乐赛 题解_前缀和_26个操作:

ACM寒假欢乐赛 题解_前缀和_27 ACM寒假欢乐赛 题解_#include_09 ACM寒假欢乐赛 题解_前缀和_29表示将i所在的那一堆移到j所在那一堆的顶上。

ACM寒假欢乐赛 题解_前缀和_30 ACM寒假欢乐赛 题解_#include_09表示一个询问,询问ACM寒假欢乐赛 题解_#include_09下面有多少个方块。

思路:

带权并查集,一堆中最顶上的方块作为父节点,用ACM寒假欢乐赛 题解_#include_33 统计X到父亲节点的距离,ACM寒假欢乐赛 题解_前缀和_34表示这个集合的大小,两者相减即为答案。

标程:

#include <bits/stdc++.h>
using namespace std;

#define
const int inf = 0x3f3f3f3f;
const int N = 300010;
const double pi = acos(-1.0);

int pre[N],num[N],dis[N];
int n;

void init() {
for(int i=0; i<n; i++) {
pre[i]=i;
num[i]=1;
dis[i]=0;
}
}
int Find(int x) {
if(x!=pre[x]) {
int t=pre[x];
pre[x]=Find(pre[x]);
dis[x]+=dis[t];
}
return pre[x];
}

int main() {
while(~scanf("%d",&n)) {
init();
char op;
while(n--) {
scanf(" %c",&op);
int x,y;
if(op=='M') {
scanf("%d %d",&x,&y);
int fx=Find(x);
int fy=Find(y);
if(fx!=fy) {
pre[fy]=fx;
dis[fy]=num[fx];
num[fx]+=num[fy];
}
} else {
scanf("%d",&x);
int fx=Find(x);
printf("%d\n",num[fx]-dis[x]-1);
}
}
}
return 0;
}

F.1421

原题链接:

​http://acm.hdu.edu.cn/showproblem.php?pid=1421​

题意:

ACM寒假欢乐赛 题解_#include_08(ACM寒假欢乐赛 题解_前缀和_36)个数中选出k对数(即ACM寒假欢乐赛 题解_i++_37个),使它们的差的平方和最小。

思路:

显然,如果要让疲劳度最低那么一定要选择重量相邻的,所以要对所有的物品按照重量进行一次排序

ACM寒假欢乐赛 题解_前缀和_38ACM寒假欢乐赛 题解_#include_09个物品,从中挑ACM寒假欢乐赛 题解_前缀和_29对物品的最小可能疲劳度,显然这个状态只能来自于ACM寒假欢乐赛 题解_#include_41ACM寒假欢乐赛 题解_i++_42两种,分别处理。

状态转移方程式为:

ACM寒假欢乐赛 题解_#include_43

ACM寒假欢乐赛 题解_i++_44ACM寒假欢乐赛 题解_#include_45

标程:

#include<bits/stdc++.h>
using namespace std;
const int inf = 0xfffffff;
const int N = 2e3+10;
int a[N],dp[N][N];
int main() {
int n,k;
while(cin>>n>>k) {
for(int i=0; i<n; i++) {
cin >> a[i];
}
for(int i=0; i<=n; i++) {

for(int j=0; j<=k; j++) {
j == 0 ? dp[i][j] = 0 :dp[i][j] = inf;
}
}
sort(a,a+n);
for(int i=2; i<=n; i++) {
for(int j=1; j<=k&&j<=i; j++) {
dp[i][j] = min(dp[i-1][j], dp[i-2][j-1] + (a[i-1]-a[i-2])*(a[i-1]-a[i-2]));
}
cout << dp[n][k] << endl;
}
}
return 0;
}

G.1376

原题链接:

​http://poj.org/problem?id=1376​

题意:

给定地图、起点、终点、初始方向,从起点开始每次操作能够向当前方向前进1~3格或者旋转90度改变方向,问最少需要几次操作才能到达终点。

思路;

先转换地图,开一个数组,当遇到不能走的方格的时候即输入值为ACM寒假欢乐赛 题解_i++_24的时候,就把此时的ACM寒假欢乐赛 题解_#include_09ACM寒假欢乐赛 题解_前缀和_29看成点,ACM寒假欢乐赛 题解_前缀和_49,这样标记完成以后,这个面就变成了一个个点,并且此时的机器人是有半径的,所以在走的时候不可能走到边界上,然后ACM寒假欢乐赛 题解_#include_50就行了。要注意一次能走ACM寒假欢乐赛 题解_#include_51格。

标程:

#include<stdio.h>
#include<queue>
#include<string.h>
#include<algorithm>
using namespace std;
struct note {
int x,y,id,s;
bool operator == (const note &a) const {
return a.y==y&&a.x==x;
}
} st,ed;
int vis[100][100][10];
int mp[100][100];
int n,m;
int dir[4][2]= {0,1,1,0,0,-1,-1,0};
int check(int x,int y,int id) {
if(x>0&&y>0&&x<n&&y<m&&vis[x][y][id]==0)
return 1;
return 0;
}
int bfs() {
queue<note>Q;
memset(vis,0,sizeof(vis));
st.s=0;
Q.push(st);
note now,temp;
while(!Q.empty()) {
now=Q.front();
Q.pop();
if(now==ed) {
printf("%d\n",now.s);
return 1;
}

temp=now;
temp.s++;
temp.id=(temp.id+1)%4;
if(vis[temp.x][temp.y][temp.id]==0) {
vis[temp.x][temp.y][temp.id]=1;
Q.push(temp);
}
temp=now;
temp.s++;
temp.id=(temp.id-1+4)%4;
if(vis[temp.x][temp.y][temp.id]==0) {
vis[temp.x][temp.y][temp.id]=1;
Q.push(temp);
}

for(int i=1; i<=3; i++) {
temp=now;
temp.x=now.x+dir[temp.id][0]*i;
temp.y=now.y+dir[temp.id][1]*i;
if(mp[temp.x][temp.y]==1)break;
if(check(temp.x,temp.y,temp.id)) {
temp.s++;
vis[temp.x][temp.y][temp.id]=1;
Q.push(temp);
}
}
}
return 0;
}
int main() {
while(~scanf("%d%d",&n,&m)&&(n+m)) {
int t;
memset(mp,0,sizeof(mp));
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
scanf("%d",&t);
if(t==1) {
mp[i][j]=mp[i+1][j]=mp[i][j+1]=1;
mp[i+1][j+1]=1;
}
}
}
scanf("%d%d%d%d",&st.x,&st.y,&ed.x,&ed.y);
char mp[20];
scanf("%s",mp);
if(mp[0]=='s')
st.id=1;
else if(mp[0]=='e')
st.id=0;
else if(mp[0]=='w')
st.id=2;
else
st.id=3;
if(bfs()==0)
printf("-1\n");
}
return 0;
}

H.6221

原题链接:

​https://codeforces.com/problemset/problem/622/A​

题意:

一个序列是ACM寒假欢乐赛 题解_前缀和_52这样排的,求第ACM寒假欢乐赛 题解_#include_08个是什么数字。

思路:

ACM寒假欢乐赛 题解_#include_08个位置属于ACM寒假欢乐赛 题解_i++_24ACM寒假欢乐赛 题解_前缀和_56,求出ACM寒假欢乐赛 题解_前缀和_56,然后ACM寒假欢乐赛 题解_i++_58就是答案了。

方法1:可以枚举ACM寒假欢乐赛 题解_i++_59ACM寒假欢乐赛 题解_前缀和_60,当ACM寒假欢乐赛 题解_#include_61大于等于ACM寒假欢乐赛 题解_前缀和_62时,ACM寒假欢乐赛 题解_i++_59就是ACM寒假欢乐赛 题解_前缀和_60了。

方法2:先让ACM寒假欢乐赛 题解_i++_65,如果ACM寒假欢乐赛 题解_i++_66,那正确的ACM寒假欢乐赛 题解_i++_59应该ACM寒假欢乐赛 题解_前缀和_68

标程:

  • 方法ACM寒假欢乐赛 题解_i++_69
#include <cstdio>
typedef long long ll;
int main() {
ll n,k=1;
scanf("%lld",&n);
while(k) {
if(k*(k+1)/2>=n)break;
k++;
}
printf("%lld\n",n-k*(k-1)/2);
return 0;
}
  • 方法ACM寒假欢乐赛 题解_i++_70
#include<cstdio>
#include<cmath>
typedef long long ll;
int main() {
ll n,k;
scanf("%lld",&n);
k=floor(sqrt(2*n));
if (k*(k+1)/2<n)k++;
printf("%lld",n-k*(k-1)/2);
return 0;
}

I.1263

原题链接:

​https://codeforces.com/problemset/problem/1263/C​

题意:

给一个ACM寒假欢乐赛 题解_#include_08让你找ACM寒假欢乐赛 题解_#include_72向下取整可以得到的值。

思路:

ACM寒假欢乐赛 题解_#include_08ACM寒假欢乐赛 题解_前缀和_74所以我们暴力枚举肯定是不超时的,但是数组会存不下,这里我们会发现一个规律就是枚举到i是ACM寒假欢乐赛 题解_前缀和_75ACM寒假欢乐赛 题解_#include_76的值一样时,后面所有的ACM寒假欢乐赛 题解_i++_77都会存在。

标程:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e7;
int ans[N];
int main() {
int T;
scanf("%d",&T);
while(T--) {
ll n;
scanf("%lld",&n);
int cut=0;
for(int l=1,r; l<=n; l=r+1) {
r=n/(n/l);
ans[cut++]=n/l;
}
ans[cut++]=0;
printf("%d\n",cut);
sort(ans,ans+cut);
for(int i=0; i<cut; ++i) {
printf("%d ",ans[i]);
}
printf("\n");
}
return 0;
}

J.1278

原题链接:

​https://codeforces.com/problemset/problem/1278/B​

题意:

对于ACM寒假欢乐赛 题解_#include_78个测试点,给两个数ACM寒假欢乐赛 题解_#include_79ACM寒假欢乐赛 题解_前缀和_80,作如下操作:

ACM寒假欢乐赛 题解_#include_09 步可以挑一个数字加 ACM寒假欢乐赛 题解_#include_09

思路;

假设操作了ACM寒假欢乐赛 题解_#include_05次。那么我们要保证$\frac{ (x+1)*x}{2} \leq abs(a-b) $。

假设最后ACM寒假欢乐赛 题解_#include_84加到了ACM寒假欢乐赛 题解_前缀和_85另外ACM寒假欢乐赛 题解_前缀和_86 ==ACM寒假欢乐赛 题解_#include_87

应该是一个偶数这时候ACM寒假欢乐赛 题解_前缀和_80应该加了ACM寒假欢乐赛 题解_前缀和_89=ACM寒假欢乐赛 题解_i++_90
这时候只需要保证为偶数ACM寒假欢乐赛 题解_i++_91就有解。因为ACM寒假欢乐赛 题解_i++_92ACM寒假欢乐赛 题解_i++_93有相同的奇偶性,所以只需要满足$abs(a-b)\leq \frac{(x+1)*x}{2} ACM寒假欢乐赛 题解_i++_94\frac{(x+1)*x}{2} +a+b$为偶数即可,所以只需要从ACM寒假欢乐赛 题解_前缀和_95开始遍历ACM寒假欢乐赛 题解_#include_05,满足条件即可输出答案。

标程:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
int T;
scanf("%d",&T);
while(T--) {
ll a,b;
scanf("%lld%lld",&a,&b);
for(ll i=0;; i++) {
ll temp=(i+1)*i/2;
if(temp>=abs(a-b)&&(a+b+temp)%2==0) {
printf("%lld\n",i);
break;

}
}
}
return 0;
}

再次声明,此次比赛为寒假欢乐赛,旨在提高大家刷题兴趣和督促大家学习,并不影响大家的正常集训学习。