A-NPY and FFT
题意:
给一个十进制数,然后将它转化为二进制数,然后对该二进制数翻转,相当于从后面看过来,最后将新的二进制转换回十进制即可。
分析:
就是普通、简单的进制转换,详见代码。
源代码:
#include <cstdio>
int main()
{
int cas;
char bina[100];
scanf("%d", &cas);
while(cas--)
{
int data, len=0;
scanf("%d", &data);
while(data) // 十进制转二进制
{
bina[len++] = data%2;
data /= 2;
}
int tmp=1, ans=0;
--len;
while(len>=0) // 反向的二进制转十进制
{
ans += bina[len--]*tmp;
tmp *= 2;
}
printf("%d\n", ans);
}
return 0;
}
B-NPY and arithmetic progression
题意:
给出4个数a1,a2,a3,a4,分别代表数字1,2,3,4的数量,问能否在使用每一个数字且仅使用1次的情况下,将给出的数据分成一些元素个数不小于3的部分,且每部分中的元素构成等差数列。
分析:
首先考虑1,2,3,4构成等差数列的情况,在元素个数不小于3的条件下,无非如下这么多种情况:(全1),(全2),(全3),(全4),(1,2,3,4),(1,2,3),(2,3,4)。既然只有这些情况满足条件,那么就可以一步一步枚举下去,搜索所有可能出现的情况。如果最终所有的数字被分配成了前面的那些情况,说明存在解法,反之如果数字的数量用完但是没有出现符合条件的情况,那么则不存在解法。所以关键就看最终剩下什么样的状态,可以想象每一次分配前面那几种情况后,最终剩下符合条件的情况只有空集,或者3个以上相同数字的集合,如果出现其它情况,则可判定无解。
源代码:
#include <cstdio>
int dfs(int a1, int a2, int a3, int a4)
{
// 全一样的成员,或无影响的空成员即满足条件
if((a1>=3||a1==0) && (a2>=3||a2==0) && (a3>=3||a3==0) && (a4>=3||a4==0))
{
return 1;
}
// 组合(1,2,3,4),如果不先搜索这组可能会暴栈
if(a1>0 && a2>0 && a3>0 && a4>0)
{
if(dfs(a1-1, a2-1, a3-1, a4-1))
{
return 1;
}
}
// 组合(1,2,3)
if(a1>0 && a2>0 && a3>0)
{
if(dfs(a1-1, a2-1, a3-1, a4))
{
return 1;
}
}
// 组合(2,3,4)
if(a2>0 && a3>0 && a4>0)
{
if(dfs(a1, a2-1, a3-1, a4-1))
{
return 1;
}
}
return 0;
}
int main()
{
int cas, a1, a2, a3, a4;
scanf("%d", &cas);
while(cas--)
{
scanf("%d%d%d%d",
&a1, &a2, &a3, &a4);
if(dfs(a1,a2,a3,a4))
{
puts("Yes");
}
else
{
puts("No");
}
}
return 0;
}
C-NPY and shot
题意:
从高h的地方,以初速度v抛物体,问在最好的仰角下物体能被抛出多远。
分析:
可以考虑从0角度开始抛物体,直到90度,很明显抛出的距离是先增后减的,也就是说抛出角度与抛出距离是成凸函数关系的,找凸函数的最大值常用的方法是三分查找,原理见另一篇文章,传送门(
点击打开链接),其实实现起来也和二分查找很类似。这样之后,就可以确定最佳的抛射角度了,剩下的就是物理问题了,其物理过程如下图:
要解这个物理模型,需要知道这么几个物理公式:
1、加速度公式
a = (vt-v0) / t
2、恒加速度下的路程公式
s = v0*t + (a*t^2)/2
有了上面的公式,就可以求解最远抛出距离问题了,最后还需要的一点知识就是速度的分解,这里按竖直和水平两个方向进行分解,然后就是利用公式及其变形来算时间、路程最终求解出答案了。
源代码:
#include <cstdio>
#include <cmath>
#define g 9.8
double v, h;
double solve(double angle)
{
// 上升到最高点所用时间(沿竖直方向计算)
double t1 = v*sin(angle) / g;
// 上升到最高点所上升的高度(沿竖直方向计算)
double h1 = v*sin(angle)*t1 - g*t1*t1/2;
// 从最高点下落到地面的时间(沿竖直方向计算)
double t2 = sqrt(2*(h1+h)/g);
// 最远抛出的距离(沿水平方向计算)
return v*cos(angle) * (t1+t2);
}
double trisection_search(double left, double right)
{
// 三分角度,找到最优解(求函数最大值下的自变量值)
double midl, midr;
while (right-left > 1e-7)
{
midl = (left + right) / 2;
midr = (midl + right) / 2;
if(solve(midl) >= solve(midr)) right = midr;
else left = midl;
}
return left;
}
int main()
{
int cas;
scanf("%d", &cas);
while(cas--)
{
scanf("%lf%lf", &h, &v);
double ans = trisection_search(0, 90);
printf("%.2f\n", solve(ans));
}
return 0;
}