目录
3.Sasha and the Beautiful Array
1.Foreign Exchange
Sample 1
Inputcopy | Outputcopy |
---|---|
4 5 7 0 3 2 2 4 3 5 2 | 5 |
Sample 2
Inputcopy | Outputcopy |
---|---|
10 32 6 46 9 37 8 33 14 31 5 5 5 3 1 4 3 2 2 3 2 3 2 4 4 3 3 3 1 | 45 |
这道题给出了有多少每国的货币,让我们求出最多可以拥有多少第n国的货币,又有第i国可以兑换第i+1国的货币的特性,我们直接将所有的第i国的货币换成i+1国的货币便可以求出第n国的货币。
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
long long n,a[200010];
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n-1;i++){
int in,out;
cin>>in>>out;
a[i+1]+=(a[i]/in)*out;//看看能换多少份
}
cout<<a[n]<<endl;
return 0;
}
注意:需要long long类型,不然会爆int!
2.Takahashi Gets Lost
Sample 1
Inputcopy | Outputcopy |
---|---|
6 7 5 LULDR ####### #...#.# ##...## #.#...# #...#.# ####### | 2 |
Sample 2
Inputcopy | Outputcopy |
---|---|
13 16 9 ULURDLURD ################ ##..##.#..####.# ###.#..#.....#.# #..##..#####.### #...#..#......## ###.##.#..#....# ##.#####....##.# ###.###.#.#.#..# ######.....##..# #...#.#.######.# ##..###..#..#.## #...#.#.#...#..# ################ | 6 |
按照给出的字符串(只含L,R,D,U),L为向左走一步,R为向右走一步,D为向下走一步,U为向上走一步。
我们可以遍历地图的每一个位置(这个位置本身要是陆地),看看执行字符串的操作会不会走到海洋,如果完成所以操作也没有走到海洋,那么此位置为一个可能落地位置,答案计数加1。
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,k,ans;
string mp[600],t;
int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};//下,上,右,左
bool check(int x,int y)
{
if(mp[x][y]=='#') return false;
for(int i=0;i<k;i++){
if(t[i]=='D')
x+=dx[0],y+=dy[0];
else if(t[i]=='U')
x+=dx[1],y+=dy[1];
else if(t[i]=='R')
x+=dx[2],y+=dy[2];
else x+=dx[3],y+=dy[3];
if(mp[x][y]=='#')//若发现当前位置不合理,直接返回错误
return false;
}
return true;//这个位置可以完成操作
}
int main()
{
cin>>n>>m>>k>>t;
for(int i=0;i<n;i++) cin>>mp[i];
for(int i=1;i<n-1;i++){//因为四周固定都是海洋,所以从1到n-2(m-2)就行
for(int j=1;j<m-1;j++){
if(check(i,j))
ans++;
}
}
cout<<ans<<endl;
return 0;
}
3.Sasha and the Beautiful Array
Sample 1
Inputcopy | Outputcopy |
---|---|
5 3 2 1 3 3 69 69 69 5 100 54 80 43 90 4 3 4 3 3 2 2 1 | 2 0 57 1 1 |
这道题没什么好讲的,直接排序,累加后一个元素减去前一个元素就是最大美丽度。
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
long long n,a[200];
int main()
{
int t;
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+1+n);
long long ans=0;
for(int i=2;i<=n;i++){
ans+=(a[i]-a[i-1]);
}
cout<<ans<<endl;
}
return 0;
}
4.Sasha and the Drawing
Sample 1
Inputcopy | Outputcopy |
---|---|
7 3 4 3 3 3 10 3 9 4 7 7 11 2 3 | 2 2 6 5 4 6 2 |
纯思路题,当然我也搞不懂原理,但是我根据图片和输入样例发现,一个着色单元格最多可以包含两条对角线,当对角线满时(也就是对角线的数量为4n-2),只需要将方形矩阵的上下两条边的单元格全部着色即可,也就是n*2个单元格。
根据上面和分析样例,于是出现了下面AC代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
long long n,k;
cin>>n>>k;
if(k==4*n-2)
cout<<n*2<<endl;
else
{
long long ans=(k+1)/2;
cout<<ans<<endl;
}
}
return 0;
}
5.Sasha and the Casino
Sample 1
Inputcopy | Outputcopy |
---|---|
9 2 1 7 2 1 1 2 3 15 3 3 6 4 4 5 5 4 7 4 88 1000000000 25 69 231 13 97 18806 | YES NO YES NO NO YES NO NO NO |
既然需要保证他能在某个时刻拥有任意个硬币,那么就要考虑连续输到下一次不会输的情况。
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ll t;
cin>>t;
while(t--)
{
ll k,x,a;
cin>>k>>x>>a;
ll f1,f2,flag=0;
f1=1;
for(int i=0;i<x-1;i++){
f2=(f1)/(k-1)+1;
f1+=f2;
if(f1>a)//要是一直输,钱不够输
{
flag=1;
break;
}
}
if(flag||(a-f1)*k<=a) cout<<"NO"<<endl;//输完,保底的本钱比原来还少也不能某个时刻达到任意钱
else cout<<"YES"<<endl;
}
return 0;
}
6.Only one of two
Sample 1
Inputcopy | Outputcopy |
---|---|
2 3 5 | 9 |
Sample 2
Inputcopy | Outputcopy |
---|---|
1 2 3 | 5 |
Sample 3
Inputcopy | Outputcopy |
---|---|
100000000 99999999 10000000000 | 500000002500000000 |
题目要求我们找出只能被n和m其中一个整除的第k个数。
第一个样例很好解释题目的要求,是不是想暴力求解,但是看这数据范围,估计算到开学也算不完。
所以我们可以想到使用二分去解决它,首先把left~right的范围定义得大一些,我们需要的答案就在这个范围里面,记得里面的数据都需要用long long类型哦!
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
long long n,m,k,l=1,r=2e18;
int gc(long long a,long long b) //找最大公约数
{
if(b) while((a%=b) && (b%=a));
return a+b;
}
int main()
{
cin>>n>>m>>k;
long long f=n*m/gc(n,m);//最大公倍数,用于减去这个数可以同时被n和m整除的情况
while(l<r){
long long mid=(l+r)/2;
if(mid/n+mid/m-mid/f*2>=k)//mid/n代表有多少个数被n整除,mid/f*2为有多少数同时被n和m整除,
r=mid;// 如果mid/n+mid/m-mid/f*2大于我们要找的第k个数,什么当前的mid大于我们要找的答案,压缩边界
else l=mid+1;
}
cout<<l<<endl;
return 0;
}
7.村村通
Sample 1
Inputcopy | Outputcopy |
---|---|
4 2 1 3 4 3 3 3 1 2 1 3 2 3 5 2 1 2 3 5 999 0 0 | 1 0 2 998 |
一个最小生成树的模板题,直接将有的边先建入,再看看还需要建多少边才能串通全部村子。
下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,pre[1001];
int find(int x)
{
if(pre[x]==x) return x;
return pre[x]=find(pre[x]);
}
int main()
{
while(scanf("%d",&n)){
if(n!=0) cin>>m;//输入停止标志
else break;
int ans=0;
for(int i=1;i<=n;i++) pre[i]=i;
while(m--){
int a,b;
cin>>a>>b;
pre[find(a)]=find(b);
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(find(i)!=find(j))
{
ans++;//建入一个边,答案+1
pre[find(i)]=find(j);
}
}
}
cout<<ans<<endl;
}
return 0;
}
8.传送门
Sample 1
Inputcopy | Outputcopy |
---|---|
4 5 1 2 3 1 3 6 2 3 4 2 4 7 3 4 2 | 14 |
对于这道题我一直在想,传送门应该要怎么建立,后面才看到这数范围(n<=100),所以是需要对任意两个教学楼都建立一次传送门,看哪个的最短路径和最小。
那就使用全源最短路径Floyd 算法来暴力求解,但是我们试想一下,这样就有5层for循环,还是会超时,所以我们需要缩减到4层。
因为只有使用了传送门才会影响最短路径,所有有了下面代码。
for(int x=1;x<=n;x++){
for(int y=1;y<=n;y++){
if(mp2[x][j]<inf&&mp2[j][y]<inf)
mp2[x][y]=min(mp2[x][y],mp2[x][j]+mp2[j][y]);
}
}
for(int x=1;x<=n;x++){
for(int y=1;y<=n;y++){
if(mp2[x][i]<inf&&mp2[i][y]<inf)
mp2[x][y]=min(mp2[x][y],mp2[x][i]+mp2[i][y]);
}
}
i,j是建传送门的教学楼,会影响最短路径,所以只需要分别对这两个教学楼的最短路径的计算更新即可。
下面是AC代码:
#include<bits/stdc++.h>
#define inf 1234567890
using namespace std;
int n,m,mp1[120][120],mp2[120][120],ans=inf;
void back()//返回原图
{
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
mp2[i][j]=mp1[i][j];
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
mp1[i][j]=inf;
for(int i=1;i<=m;i++){
int x,y,z;
cin>>x>>y>>z;
mp1[x][y]=mp1[y][x]=z;
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(mp1[i][k]<inf&&mp1[k][j]<inf)//先计算没有建立传送门的最短路径
mp1[i][j]=min(mp1[i][j],mp1[i][k]+mp1[k][j]);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
back();//每次返回原图
mp2[i][j]=mp2[j][i]=0;//建立传送门
for(int x=1;x<=n;x++){
for(int y=1;y<=n;y++){
if(mp2[x][j]<inf&&mp2[j][y]<inf)
mp2[x][y]=min(mp2[x][y],mp2[x][j]+mp2[j][y]);
}
}
for(int x=1;x<=n;x++){
for(int y=1;y<=n;y++){
if(mp2[x][i]<inf&&mp2[i][y]<inf)
mp2[x][y]=min(mp2[x][y],mp2[x][i]+mp2[i][y]);
}
}
int cnt=0;
for(int x=1;x<=n;x++){
for(int y=x+1;y<=n;y++){
cnt+=mp2[x][y];//计算最短路径和
}
}
ans=min(ans,cnt);//更新最小
}
}
cout<<ans<<endl;
return 0;
}