数字游戏
Accepts: 7247 Submissions: 13194
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
Problem Description
小蜗蜗有 n n n 个数字(实数),但他不知道这些数字具体是啥。
他只知道这 n n n 个数字的最大值、最小值和平均值,但也不一定是对的。
现在,小蜗蜗想知道,存不存在一种方案,使得这 nn 个数字的最大值、最小值和平均值恰好等于给定值。
Input
第一行读入一个整数 t e s t ( 1 ≤ t e s t ≤ 100000 ) test(1\leq test \leq 100000) test(1≤test≤100000) 表示数据组数。
接下来 t e s t test test 行,每行四个整数 n , m a x , m i n , a v e ( 1 ≤ n ≤ 100000 , − 100 ≤ m a x , m i n , a v e ≤ 100 ) n, max, min, ave(1 \leq n \leq 100000, -100 \leq max, min, ave \leq 100) n,max,min,ave(1≤n≤100000,−100≤max,min,ave≤100) 分别表示最大值、最小值和平均值。
注意,一开始的 n n n 个数字的取值范围是实数。
Output
输出共 t e s t test test 行。
对于第 i i i 行,如果存在一组合法方案,输出 yes,否则输出 no。
Sample Input
2
3 1 1 1
2 3 1 1
Sample Output
yes
no
思路
首先特判 n = = 1 n==1 n==1 的情况,对于其他情况,计算 n n n 个数之和的最大值 ( n − 1 ) × m a x + m i n (n-1)\times max+min (n−1)×max+min,最小值 ( n − 1 ) × m i n + m a x (n-1)\times min+max (n−1)×min+max,若 a v g × n avg\times n avg×n 在二者之间,则符合要求,否则不符合。
比较坑的是,输入的 m a x max max 未必比 m i n min min 大,所以需要判断 m a x ≥ a v g ≥ m i n max \geq avg\geq min max≥avg≥min,若不满足这一条件,直接输出no。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int T,n,mx,mn,avg;
void solve(){
int mnn,mxn;
cin>>n>>mx>>mn>>avg;
if(mx>=mn&&avg<=mx&&avg>=mn){
if(n==1){
if(mx==mn&&mn==avg){ cout<<"yes\n"; return; }
else{ cout<<"no\n"; return; }
}
mnn=mxn=mx+mn;
avg*=n;
if(n-2>0) mxn+=(n-2)*mx;
if(n-2>0) mnn+=(n-2)*mn;
if(avg>=mnn&&avg<=mxn) cout<<"yes\n";
else cout<<"no\n";
}else{
cout<<"no\n";
}
}
signed main(){
ios::sync_with_stdio(false);
for(cin>>T;T;T--) solve();
}
网格路径
Accepts: 735 Submissions: 3776
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
Problem Description
给定一张 n × n n\times n n×n 的网格图,有些格子能走,有些格子不能走,左上角的格子坐标为 ( 1 , 1 ) (1,1) (1,1),右下角的格子坐标为 ( n , n ) (n,n) (n,n)。
问最多可以找到多少条从 ( 1 , 1 ) (1,1) (1,1) 到 ( n , n ) (n,n) (n,n) 的不相交路径,使得每条路径经过的每个格子(包含 ( 1 , 1 ) (1, 1) (1,1) 和 ( n , n ) (n, n) (n,n))都是能走的格子?
每次我们只可以向右或向下走,不能离开网格图的边界。两条路径不相交当且仅当除了格子 ( 1 , 1 ) (1,1) (1,1) 和 ( n , n ) (n,n) (n,n),它们没有任何公共部分。
Input
第一行一个整数 t e s t ( 1 ≤ t e s t ≤ 1000 ) test(1\leq test \leq 1000) test(1≤test≤1000) 表示数据组数。
对于每组数据,第一行一个整数 n ( 2 ≤ n ≤ 10 ) n(2\leq n \leq 10) n(2≤n≤10) 表示网格图的大小。
接下来 n n n 行,每行一个长度为 n n n 的字符串。第 i i i 行第 j j j 列的字符 ‘.’ 表示 ( i , j ) (i,j) (i,j) 可以走,’#’ 表示不能走。
Output
对于每组数据,输出一行一个整数表示最多可以找到的不相交路径数目。
Sample Input
3
2
..
..
3
...
.##
...
3
.#.
#..
...
Sample Output
2
1
0
思路
最多有两条路径,所以主要是判断答案为 1 1 1 还是为 2 2 2 。
可以用深搜找出一条尽量靠右的路,把走过的路标记为已访问。在走一条尽量靠下的路。
特判 m p [ 1 ] [ 1 ] mp[1][1] mp[1][1] 和 m p [ n ] [ n ] mp[n][n] mp[n][n] ,若它们不能走,则答案直接为 0 0 0 。
#include<bits/stdc++.h>
using namespace std;
const int rdir[2][2]={{0,1},{1,0}};
const int ldir[2][2]={{1,0},{0,1}};
int T,n,vis[20][20];
char mp[20][20];
bool dfs(int x,int y,int flag){
vis[x][y]=1;
for(int k=0;k<2;k++){
int xx,yy;
if(flag) xx=x+rdir[k][0],yy=y+rdir[k][1];
else xx=x+ldir[k][0],yy=y+ldir[k][1];
if(xx==n&&yy==n) return true;
if(xx<=n&&y<=n&&x>0&&y>0&&mp[xx][yy]=='.'&&vis[xx][yy]==0){
vis[xx][yy]=1;
if(dfs(xx,yy,flag)) return true;
}
}
return false;
}
void solve(){
int ans=0;
scanf("%d",&n);
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++) scanf("%s",mp[i]+1);
if(mp[1][1]=='#'||mp[n][n]=='#'){ printf("0\n"); return; }
if(dfs(1,1,1)) ans++;
if(dfs(1,1,0)) ans++;
printf("%d\n",ans);
}
int main(){
for(scanf("%d",&T);T;T--) solve();
}
虫族基地
Accepts: 195 Submissions: 1613
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
Problem Description
有一个 n × m n \times m n×m 的网格,左上角的格子坐标为 ( 1 , 1 ) (1,1) (1,1),右下角的格子坐标为 ( n , m ) (n,m) (n,m)。
初始的时候,网格上有两个虫族基地,其中一个在第一行,另一个在最后一行。 对于每个虫族基地,在第 i 2 i^2 i2 秒结束的时候,与虫族基地曼哈顿距离为 i i i 的格子会被虫族占领。
有一批物资要从 ( 1 , 1 ) (1,1) (1,1) 运送到 ( n , m ) (n,m) (n,m),每次我们可以走上下左右四个方向,我们不能离开网格图的边界。
物资经过的路径(包含起终点)不能存在任何被虫族占领的格子(虫族基地也不行)。
请问第几秒结束时,从 ( 1 , 1 ) (1,1) (1,1) 到 ( n , m ) (n,m) (n,m) 的联系会被切断?(不存在一条从左上到右下的路径)
Input
第一行一个正整数 t e s t ( 1 ≤ t e s t ≤ 100000 ) test(1 \le test \le 100000) test(1≤test≤100000) 表示数据组数。
对于每组数据,一行四个整数 n , m , x 1 , x 2 ( 1 ≤ n , m ≤ 1000000000 , 1 ≤ x 1 , x 2 ≤ m ) n, m, x_1, x_2(1\le n,m\le 1000000000, 1\le x_1, x_2 \le m) n,m,x1,x2(1≤n,m≤1000000000,1≤x1,x2≤m)。两个虫族基地的坐标分别为 ( 1 , x 1 ) (1, x_1) (1,x1) 和 ( n , x 2 ) (n, x_2) (n,x2)。
Output
对于每组数据,输出一行一个整数表示答案。
Sample Input
3
2 2 2 1
3 3 3 1
3 3 1 1
Sample Output
0
1
0
思路
不断更新道路被切断时间的最小值
m
n
mn
mn 。首先,若是起点
(
1
,
1
)
(1,1)
(1,1) 或是终点
(
n
,
n
)
(n,n)
(n,n) 被占领,则被切断;若是蚁群纵向从
1
1
1 占领到
n
n
n,那么也被切断;计算两个蚁群之间的曼哈顿距离
m
h
d
L
e
n
mhdLen
mhdLen ,若是两个蚁群的横坐标相同,那么用
m
h
d
L
e
n
2
\frac {mhdLen} 2
2mhdLen 更新最小值,否则,用
m
h
d
L
e
n
−
1
2
\frac{mhdLen-1}{2}
2mhdLen−1 更新最小值。
最后特判一下最小值会不会小于
0
0
0,若小于
0
0
0,则置零。输出
m
n
2
mn^2
mn2
#include<bits/stdc++.h>
#define int long long
using namespace std;
int T,n,m,x,y;
void solve(){
cin>>n>>m>>x>>y;
int mn=min(x-1,m-y);
mn=min(mn,n-1);
int mhdLen=abs(x-y)+n-1;
if(x==y) mn=min(mn,(n-1)/2);
else mn=min(mn,(mhdLen-1)/2);
if(mn<0) mn=0;
cout<<mn*mn<<endl;
}
signed main(){
ios::sync_with_stdio(false);
for(cin>>T;T;T--) solve();
}
环上游走
Accepts: 535 Submissions: 1166
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 32768/32768 K (Java/Others)
Problem Description
有一个环,环上有 n n n 个位置,它们的编号为 1... n 1...n 1...n。
位置 i ( 1 < i < n ) i(1 < i < n) i(1<i<n) 左右两边分别是位置 i − 1 i-1 i−1 和位置 i + 1 i+1 i+1,位置 1 1 1 左右两边分别是位置 n n n 和位置 2 2 2,位置 n n n 左右两边分别是位置 n − 1 n-1 n−1 和位置 1 1 1。
现在,我们要玩一个游戏。初始我们在位置 1 1 1,游戏共 n − 1 n-1 n−1 轮,对于第 i ( 1 ≤ i < n ) i(1 \le i < n) i(1≤i<n) 轮,我们可以选择从当前位置往左或往右连续走 i i i 个位置。
现在我们想知道,对于给定的 n n n,有多少种方案,使得我们停留的 n n n 个位置(初始的位置 1 1 1 和 n − 1 n-1 n−1 轮中每一轮结束时候的位置)没有重复。
Input
第一行一个整数 t e s t ( 1 ≤ t e s t ≤ 80 ) test(1 \le test \le 80) test(1≤test≤80) 表示数据组数。
对于每组数据,一行一个整数 n ( 1 ≤ n ≤ 80 ) n(1 \le n \le 80) n(1≤n≤80) 表示环的大小。
Output
对于每组数据,一行一个整数表示答案。
Sample Input
4
2
3
4
5
Sample Output
2
2
4
2
思路
这题先是深搜交一发,超时了,就打个表,过了。
不过也有别人写的深搜就过了,但是赛后同样的代码再交一次,还会超时。可能是比赛时的测评机有优化。
//深搜超时代码
#include<bits/stdc++.h>
using namespace std;
int T,n,ans;
bitset<80> b;
void dfs(int p,int step){
if(step==n) return void(ans++);
int np=p+step; if(np>n) np-=n;
if(b[np]==0){ b[np]=1; dfs(np,step+1); b[np]=0; }
np=p-step+n; if(np>n) np-=n;
if(b[np]==0){ b[np]=1; dfs(np,step+1); b[np]=0; }
}
void solve(){
ans=0; cin>>n;
b[1]=1,dfs(1,1);
cout<<ans<<endl;
}
int main(){
ios::sync_with_stdio(false);
for(cin>>T;T;T--) solve();
}
#include<bits/stdc++.h>
using namespace std;
int T,n,a[100]={0,1,2,2,4,2,4,4,8,2,4,6,8,2,8,6,16,2,4,6,8,4,12,6,16,4,4,4,16,2,12,10,32,4,4,8,8,2,12,6,16,2,8,6,24,6,12,8,32,6,8,6,8,2,8,10,32,4,4,6,24,2,20,6,64,6,8,8,8,4,16,6,16,2,4,8,24,14,12,6,32};
int main(){
scanf("%d",&T);
while(T--){
scanf("%d",&n);
printf("%d\n",a[n]);
}
}