鏖战4小时多 过了9个题
A题输入过于阴间,不会转化成建树。
K读不太懂 - -
C - Coolest Ski Route (C题)
给了我们n个点以及m条有边权的边,因为是滑雪,所以是单向边,问从一个点出发能最远滑多远.
分析: 直接存一下图 然后dfs 每个点 加了一点记忆化就过了
vector <pair<ll,ll> >vec[1100];
ll cnt[1100];
ll dfs(ll rt){
if(cnt[rt]!=-1){
return cnt[rt];
}
ll sum=0;
for(int i=0;i<vec[rt].size();i++){
sum=max(sum,vec[rt][i].second+dfs(vec[rt][i].first));
}
return cnt[rt]=sum;
}
signed main(){
ll n,m;
read(n);
read(m);
memset(cnt,-1,sizeof(cnt));
while(m--){
ll u,v,w;
read(u);
read(v);
read(w);
vec[u].push_back(mp(v,w));
}
ll add=0;
for(int i=1;i<=n;i++){
add=max(add,dfs(i));
}
printf("%lld\n",add);
}
Down the Pyramid D题
按题目意思说的就是一种搭建金字塔,使得一个块下面两个块的和与它相等,现在他给了我们n个数,我们要构造他下面的n+1块砖是什么值符合构造的种数有多少种。
分析: 其实想一想 就是一个范围的维护 维护结束的【L R】区间就是答案
int a[maxn];
signed main() {
IOS;
int n;cin>>n;
FOR2(i,1,n) cin>>a[i];
int maxx=a[1],minn=0;
int cnt=a[1];
FOR2(i,2,n) {
cnt=a[i]-cnt;
if(i&1) maxx=min(maxx,cnt);
else minn=max(minn,0-cnt);
}
if(maxx<minn) cout<<0;
else cout<<maxx-minn+1;
return 0;
}
E - Expired License E 题
题目大概意思就是 给你两个实数,问存不存在两个素数的比值跟他俩的比值是一模一样的,不存在输出imporisble 题目的实数保证小数点后最多5位,我直接字符串输入把实数变成整数。
如果a : b = prime _1: prime_2
因为质数已经是最简型了,所以直接把a .b 除去gcd 再判断剩下的是不是都是质数就OK 注意特判 2 2 的情况
F - Fighting Monsters F 题
挺简单的,推一下式子你会发现就是问你n个数里面有没有相邻的两项斐波那契数列
H - Hyper Illuminati 这个直接暴力枚举就OK
I - It’s Time for a Montage 暴力枚举
L - Logic Puzzle L题
意思是一张nm的地雷图,现在给你(n+2)(m+2)的地雷数量分布情况,意思是以地雷图中的点的坐标为中心的3*3矩阵,现在问我们能不能还原回去那个地雷图或者说明这个是不可能的 。
分析: 没有地雷的点 它的一圈必定有0而且没有负数 不管什么时候只要有负数一定无法构造。那么我的思路就是枚举地雷图 依次check
如果此处没地雷就填一个。 有地雷就把它的一圈全部 -1 最终检查一次整个地雷分布情况是不是全是0 ,然后输出已经存下的地雷图
ll mapp[500][500];
char s[500][500];
ll check(ll x,ll y){
// 以x y为中心的 3*3 矩阵
ll f=0;
ll NO=0;
ll Y=0;
// 判断是不是 。
for(int i=x-1;i<=x+1;i++){
for(int j=y-1;j<=y+1;j++){
if(mapp[i][j]==0){
f++;
}
if(mapp[i][j]<0){
NO++;
}
if(mapp[i][j]>0){
Y++;
}
}
}
if(NO){
printf("impossible\n");
// printf("%lld %lld\n",x,y);
exit(0);
}
if(f){
// 该点为0
return 0;
}
if(Y==9){
for(int i=x-1;i<=x+1;i++){
for(int j=y-1;j<=y+1;j++){
mapp[i][j]--;
}
}
return 1;
}
}
ll n,m;
void init(){
for(int i=1;i<=n+2;i++){
for(int j=1;j<=m+2;j++){
printf("%lld ",mapp[i][j]);
}
printf("\n");
}
printf("--------------------\n");
}
signed main(){
read(n);
read(m);
for(int i=1;i<=n+2;i++){
for(int j=1;j<=m+2;j++){
read(mapp[i][j]);
}
}
for(int i=2;i<=n+1;i++){
for(int j=2;j<=m+1;j++){
ll op=check(i,j);
// init();
if(op==0){
s[i][j]='.';
continue;
}
if(op==1){
s[i][j]='X';
}
}
}
for(int i=1;i<=n+2;i++){
for(int j=1;j<=m+2;j++){
if(mapp[i][j]!=0){
printf("impossible");
return 0;
}
}
}
for(int i=2;i<=n+1;i++){
for(int j=2;j<=m+1;j++){
printf("%c",s[i][j]);
}
printf("\n");
}
}
M - Mountaineers M题
辛格牛逼~~
其实LCA也能跑 。
B题 B - Battle Royale 计算几何
给了我们两个点A B的坐标并给了两个圆的信息, 大圆把小圆包含着,现在求从A 到B 且不经过小圆,不走出大圆的最短路径。保证A B的直线距离是横穿小圆的。
分析: 草稿纸上简单证明了下,A,B点并不会直接向着圆心走到⚪上,这样子的距离比从切线走到圆上要长,这一点很显然。那么相当于求A走切线再走圆弧再走B的切线这两段路程。
那么直接算一下A到圆心,B到圆心,AB的距离,构造三角形算一下圆心角的弧度,另外的减去两段多余的弧度,最终勾股定理求一下点到切点的距离 ,搞了一个小时才AC