NYSIT第四次周賽題解
NYIST–2018大一新生第四次周賽
連結:https://cn.vjudge.net/contest/269128 密碼:nyist
A - 穆穆清風至 HDU - 2550
畫圖,模擬一下即可
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; struct Node{ int len,num; }node[110]; void Print(int len)//輸出一行長度為len 的弓箭 { printf(">+"); for(int i=0;i<len-2;++i) printf("-"); printf("+>\n"); } bool cmp(Node a,Node b)//將短的放前面 { return a.len<b.len; } int main() { int t,n; scanf("%d",&t); while(t--) { scanf("%d",&n); for(int i=0;i<n;++i) scanf("%d %d",&node[i].len,&node[i].num); sort(node,node+n,cmp); for(int i=0;i<n;++i) { for(int j=0;j<node[i].num;++j)//每一種箭 輸出num個 Print(node[i].len); printf("\n"); } } return 0; }
B - 無法提交 CodeForces - 702A
求最大連續嚴格遞增長度
思路:記錄當前嚴格遞增長度和上一個數,每輸入一個數判斷是否與前面那個數構成嚴格遞增關係,更新變數即可。
#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> #define maxn 110 using namespace std; int main() { int maxlen,n,val,lastval; while(~scanf("%d",&n)) { lastval=-1;//上一個數 maxlen=-1;//最長的連續遞增長度 int cnt=0;//現在當前有多少個連續的嚴格遞增數 /* 每次在輸入數時變數代表的意義 val:現在輸入的數 lastval:上一個數(初始值為-1) cnt:現在當前有多少個連續的嚴格遞增數 maxlen:最大的cnt */ while(n--) { scanf("%d",&val); if(val>lastval)//還保持嚴格遞增 cnt++; else//不能保持嚴格遞增 { if(maxlen<cnt)//更新 maxlen=cnt; cnt=1; } lastval=val; } if(maxlen<cnt) maxlen=cnt; printf("%d\n",maxlen); } }
C - 吹我羅衣裾 HDU - 2003
題目都說了用double ,float的精度較低
#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> #define maxn 1100 using namespace std; int main() { double k; while(~scanf("%lf",&k)) { if(k<0.0) k=-1.0*k; printf("%.2lf\n",k); } }
D - 青袍似春草 HDU - 1420
快速冪模板,注意A,B,C<=1000000,A*A的過程可能會爆int(1e9),所以用需要用long long
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define maxn 1100
using namespace std;
typedef long long ll;
ll quick_pow(ll a,ll b,ll mod)//快速冪板子,可以記下來
{
ll ans=1;
while(b)
{
if(b&1)
ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
int main()
{
ll a,b,mod,ans;
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld %lld %lld",&a,&b,&mod);
printf("%lld\n",quick_pow(a,b,mod));
}
}
E - 無法提交 CodeForces - 977A
k的值較小,模擬一下過程即可
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define maxn 110
using namespace std;
int main()
{
int n,k;
scanf("%d %d",&n,&k);
while(k)
{
if(n%10)
n--;
else
n/=10;
--k;
}
printf("%d\n",n);
}
F - 無法提交 CodeForces - 510A
簡單畫圖題,模擬過程即可
/*
輸出第k行:
k為奇數: 輸出m個'#' (#####)
k為4的倍數: 輸出一個'#' m-1個'.' (#..)
k是2的倍數但是不是4的倍數:輸出 m-1個'.' 一個'#' (..#)
輸出n行即可
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define maxn 110
using namespace std;
int main()
{
int n,m;
scanf("%d %d",&n,&m);
for(int i=1; i<=n; ++i)
{
if(i&1)//i為奇數
for(int j=1; j<=m; ++j)
printf("#");
else
{
if(i%4==0)//i是4的倍數 輸出#..
{
printf("#");
for(int j=1; j<=m-1; ++j)
printf(".");
}
else
{
for(int j=1; j<=m-1; ++j)
printf(".");
printf("#");
}
}
printf("\n");
}
}
G - 無法提交 CodeForces - 501A
我相信你讀完這道題就能A
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define maxn 110
using namespace std;
int main()
{
int a,b,c,d;
int score1,score2;
while(~scanf("%d %d %d %d",&a,&b,&c,&d))
{
score1=max(3*a/10,a-(a/250)*c);
score2=max(3*b/10,b-(b/250)*d);
if(score1==score2)
printf("Tie\n");
else
printf("%s\n",score1>score2?"Misha":"Vasya");
}
}
H - 安得抱柱信 HihoCoder - 1768
找規律題吧,我做這道題暴力了一遍,發現在5位數以內滿足條件的只有2,3,5,7,23,37,53,73,373這9個數,所以就猜應該只有這9個數。因為一個5位數可以看作左邊是一個1位數,右邊是一個4位數,因為四位數中沒有“真素數”所以五位數一定不會是一個“真素數”(因為“真素數“滿足其左邊和右邊都是”真素數“)。然後擴充套件一下,得到超過5位數的數的都不會是“真素數”,所以”真素數“就只有這9個數了
AC程式碼:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define maxn 1100000
using namespace std;
typedef long long ll;
int ans[]={2,3,5,7,23,37,53,73,373};
int main()
{
int n;
while(~scanf("%d",&n))
{
if(n<=9)
printf("%d\n",ans[n-1]);
else
printf("-1\n");
}
}
暴力過程的程式碼:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define maxn 1100000
using namespace std;
typedef long long ll;
int prime[maxn];
int Solve(int k)//判斷k是不是真正的素數
{
int wis[10];
int len=0;
while(k)
{
wis[len++]=k%10;
k/=10;
}//注意陣列中的數存的順序是從低位到高位的
for(int i=len-1;i>=0;--i)
{
for(int j=i;j>=0;--j)//取i j之間的數字(包括i j下標)
{
int val=0;
for(int k=i;k>=j;--k)//求 i j之間的數字為多少
{
val*=10;
val+=wis[k];
}
if(prime[val])
return 0;
}
}
return 1;
}
int main()
{
prime[0]=prime[1]=1;//非素數用 1表示
for(int i=2;i<=1000;++i)
{
if(!prime[i])
{
for(int j=i*i;j<=1000000;j+=i)
prime[j]=1;
}
}
for(int i=1;i<=1000000;++i)
{
if(Solve(i))
printf("%d\n",i);
}
}
I - 皎日以為期 HihoCoder - 1051
思路:
貪心問題,m次補籤卡,求最長連續登陸天數,
補籤卡夠直接輸出100.
如果不能全補籤,就列舉m個補籤卡的位置(一定是連續的)。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define maxn 110
using namespace std;
int day[maxn];
int main()
{
int t,n,m;
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&m);
day[0]=0;
for(int i=1;i<=n;++i)
{
scanf("%d",day+i);
}
if(m>=n)//可以全部補籤
{
printf("100\n");
continue;
}
int ans=-1;
for(int i=0;i<=n-m;++i)//列舉範圍即可
{
if(day[m+i+1]-day[i]-1>ans)//第i 和第m+i+1之間的補籤 得到連續的天數=day[m+i+1]-day[i]-1
ans=day[m+i+1]-day[i]-1;
}
printf("%d\n",ans);
}
}
J - 新加題1 HihoCoder - 1712
思路:
"一般我們在對字串排序時,都會按照字典序排序。當字串只包含小寫字母時,相當於按字母表"abcdefghijklmnopqrstuvwxyz"的順序排序。現在我們打亂字母表的順序,得到一個26個字母的新順序。例如"bdceafghijklmnopqrstuvwxyz"代表’b’排在’d’前,'d’在’c’前,'c’在’e’前…… "
將給出的26個小寫字母依此當成a~z即可,進行排序即可,因為要輸出字串,所以需要記下未轉化前的字串
給定一個結構體:裡面有兩個元素s1 s2都為char陣列,s1為輸入字串,s2為轉化後的字串,然後結構體排序即可。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define maxn 110
using namespace std;
struct Node{
char s1[maxn],s2[maxn];
}node[1100];
int bm[30];
bool cmp(Node a,Node b)
{
int val=strcmp(a.s2,b.s2);
return val<0;//代表排序過後 字串小的在前面
}
int main()
{
int n;
scanf("%d",&n);
char ss[30];
scanf("%s",ss);
for(int i=0;i<26;++i)
bm[ss[i]-'a']=i;//bm[k]的意思k+'a'對應的字元為bm[k]+‘a’
for(int i=0;i<n;++i)
{
scanf("%s",node[i].s1);
int len=strlen(node[i].s1);
for(int j=0;j<len;++j)
node[i].s2[j]=bm[node[i].s1[j]-'a']+'a';
node[i].s2[len]='\0';
}
sort(node,node+n,cmp);//排序
for(int i=0;i<n;++i)
{
printf("%s\n",node[i].s1);
}
}
K - 新加題2 HihoCoder - 1562
思路:
根據當前時間和過的秒數,計算出最後的時間,根據最後時間的小時 分鐘 秒 計算出時針的角度和分針角度 即可
程式碼:
/*
K - 新加題2
*/
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define maxn 110
/*
1.計算最後的 h m s
2.計算此時的時針與分針夾角
因為夾角只與最後針的位置與關,所以保證h m s在一定範圍內,用公式求出夾角即可
時針: 1h 轉60° 1min轉0.5° 1s轉 (0.5/60)°
分針: 60min轉360 1min轉 6° 1s轉0.1°
*/
using namespace std;
int main()
{
int bh,bm,bs;//開始時鐘的時刻
int hh,mm,ss;//最後時鐘的時刻
int t,T;
float mines_angle,hour_angle;
float ans;
scanf("%d",&T);
while(T--)
{
scanf("%d %d %d",&bh,&bm,&bs);
scanf("%d",&t);
ss=bs+t%60;
t/=60;
mm=bm+t%60;
t/=60;
hh=bh+t;
mm+=ss/60;
ss=ss%60;//保證秒針的值在0~59
hh+=mm/60;
mm=mm%60;//保證分針的值在0~59即可
hh%=12;//保證時針在0~11之內
mines_angle=(float)mm*6.0+(float)ss*0.1;
hour_angle=(float)hh*30.0+(float)mm*0.5+(float)ss*(0.5/60.0);
ans=hour_angle-mines_angle;
if(ans<0.0)
ans*=-1.0;
if(ans>180.0)
ans=360.0-ans;
printf("%.4f\n",ans);
}
}