题目链接:http://www.gdutcode.sinaapp.com/contest.php?cid=1057

Problem A: 两只老虎

解析:列个方程直接可以解出答案,ans = a/2-c/4+b

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+100;
int main()
{
int t;
cin>>t;
while(t--)
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
int t1 = c/4-b;
int ans = a/2-t1;
printf("%d\n",ans);

}
return 0;
}

Problem D: 只有通过毁灭才能揭示真理

解析:直接算就好了

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+100;
const int mod = 10007;
int main()
{
int t;
cin>>t;
while(t--)
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
int ans = a*b+a/30*c;
printf("%d\n",ans);
}
return 0;
}

Problem C: 爬楼梯

解析:数多几个,发现是类斐波那契数列的东西,先把每层的方法数处理好,然后直接相乘即可

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+100;
const int mod = 10007;
int dp[25];
int main()
{
dp[1] = 1;
dp[2] = 2;
dp[3] = 4;
for(int i=4;i<=20;i++)
dp[i] = dp[i-1]+dp[i-2]+dp[i-3];
int t;
cin>>t;
while(t--)
{
int n;
scanf("%d",&n);
int ans = 1;
for(int i=0;i<n-1;i++)
{
int x;
scanf("%d",&x);
ans = (ans*dp[x])%mod;
}
printf("%d\n",ans);
}
return 0;
}

Problem E: 倒水(Water)

解析:比赛的时候没想那么多,直接dfs爆搜了

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+100;
const int inf = 0x7fffffff;
int a[maxn];
int n,k;
int ans = inf;
void dfs(int t1,int t2,int t3,int step)
{
if(step>ans)
return ;
if(t1+t2<=k)
ans = min(ans,step);
if(t1==1)
return ;
if(t1%2)
{
dfs(t1/2,t2+1,t3*2,step);
dfs((t1+1)/2,t2,t3*2,step+t3);
}
else
dfs(t1/2,t2,t3*2,step);
}
int main()
{
int t;
cin>>t;
while(t--)
{
scanf("%d %d",&n,&k);
int tt = n;
ans = 1;
while(n!=1)
{
if(n%2)
ans++;
n/=2;
}
if(ans<=k)
puts("0");
else
{
ans = inf;
dfs(tt,0,1,0);
printf("%d\n",ans);
}
}
return 0;
}

Problem H: tmk买礼物

解析:排个序,然后那个ans记录当前可以达到最大的x,然后没加一个a[i],判断他是否满足a[i]<=ans+1,不然的话会出现断层

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+100;
const int mod = 10007;
int a[maxn];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
long long ans = 0;
sort(a,a+n);
for(int i=0;i<n;i++)
{
if(a[i]<=ans+1)
ans += a[i];
else
break;
}
printf("%lld\n",ans);
}
return 0;
}

Problem B: 占点游戏

解析:首先算出两点之间的曼哈顿距离step,接着判断先手在n轮里面是否能到达对面的出发点((n+1)/2>step?),如果不能到达,n为奇数时,先手比后手多一个,n为偶数就是平手了,如果能够到达,如果曼哈顿距离为奇数时,如果n为偶数的话,先手到达时,后手可以多走一步,故为平手,若n为奇数的话,先手可以比后手多走一步,故领先两点

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+100;
const int inf = 0x7fffffff;
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
int x1,y1,x2,y2;
scanf("%d %d %d %d %d",&n,&x1,&y1,&x2,&y2);
int step = abs(x1-x2)+abs(y1-y2);
int ans;
if(n%2)
{
n/=2+1;
if(step>n)
ans = 1;
else if(step%2)
ans = 2;
else
ans = 1;
}
else
{
n/=2;
if(step>n)
ans = -1;
else if(step%2)
ans = -1;
else
ans = 1;
}
printf("%d\n",ans);
}
return 0;
}

Problem F: tmk找三角

解析:由于这个图是一棵树,所以处理最短路的时候直接dfs即可,剩下的是判断是否存在三角形,通常判断是否存在三角形的方法是,把所有边都排个序,判断a[i]是否小于a[i-1]+a[i-2],那么这样肯定是超时的,如果换种思路来考虑的话,如果无法构成三角形,则对于所有的边都有a[i]>=a[i-2]+a[i-1],加上a[i]尽量取得小的话,那就是a[i] = a[i-2]+a[i-1],且a[i-2] = a[i-1] = 1,那这就是一个斐波那契数列了,于是如果不存在三条边能够成三角形的话,那么最长的边至少为f[n],表示斐波那契第n项,而题目边最大为1e9,也就是如果n>50的话,一定是yes,如果n<=50的话,那就按常规的判断即可

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+100;
const int inf = 0x7fffffff;
struct node
{
int v;
int w;
node() {}
node(int _v,int _w)
{
v = _v;
w = _w;
}
};
vector<node>G[maxn];
int du[maxn];
int dis[maxn];
int fa[maxn];
void init(int n)
{
for(int i=0;i<=n;i++)
{
G[i].clear();
fa[i] = i;
}
memset(du,0,sizeof(du));

}
void dfs(int u,int d)
{
du[u] = d;
for(int i=0;i<G[u].size();i++)
{
node now = G[u][i];
if(now.v == fa[u])
continue;
dis[now.v] = now.w;
fa[now.v] = u;
dfs(now.v,d+1);
}
}
int slove(int x,int y)
{
vector<int>ans;
while(ans.size()<50 && x!=y)
{
if(du[x]<du[y])
{
ans.push_back(dis[y]);
y = fa[y];
}
else
{
ans.push_back(dis[x]);
x = fa[x];
}
}
if(ans.size()>=50)
return 1;
sort(ans.begin(),ans.end());
for(int i=2;i<ans.size();i++)
{
if(ans[i]<ans[i-1]+ans[i-2])
return 1;
}
return 0;
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
scanf("%d",&n);
init(n);
for(int i=0;i<n-1;i++)
{
int a,b,len;
scanf("%d %d %d",&a,&b,&len);
G[a].push_back(node(b,len));
G[b].push_back(node(a,len));
}
dfs(1,0);
int q;
scanf("%d",&q);
while(q--)
{
int x,y;
scanf("%d %d",&x,&y);
if(slove(x,y))
puts("Yes");
else
puts("No");
}
}
return 0;
}