历史性突破,第一次AC三道题,有点小激动
1、酷炫双节棍
题目描述
小希现在手里有一个连着的两块木条,长度分别为l1,l2,木条之间有一个无摩擦的连接点,木条之间可以相互转动,小希将其称之为双截棍。
现在小希把长为l1的木条的一端放在原点(0,0),任意转动这两根木条,小希想知道,是否有可能通过一种转动方式使得双截棍的另一端到达指定点呢?
如果不能,请输出所有能到达的点中离目标点最近的距离。
输入描述:
第一行输入一个两个正整数l1,l2,表示木条长度。
第二行输入一个正整数T,表示询问次数。
随后T行,每行两个实数xi,yi表示目标点的坐标。
l1,l2≤1000
T≤1000
|x|,|y|≤10000
输出描述:
对于每次询问,如果可以到达,输出0,如果无法到达,给出所有能到达的点中离目标点最近的距离。
你的答案将被认为是正确的,如果相对误差不大于1e-6。
示例1
输入
23 13
3
15 1
40 0
0 0
输出
0.00000000
4.00000000
10.00000000
送温暖的题目居然WA了14次,算是自暴自弃了直接,最后发现输入的坐标也有可能是浮点数,注意到这点两个方法就都过了。第一个方法是分情况讨论,第二个则是更精简的方法,大体做法画一下就可以出来。
方法一AC:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int l1,l2;
cin>>l1>>l2;
int n;
double ans;
cin>>n;
while(n--)
{
double t1,t2;
cin>>t1>>t2;
long double l=sqrt(t1*t1+t2*t2);
if(l1>=l2)
{
if(l>=(l1-l2)&&l<=(l1+l2))
ans=0;
else if(l<(l1-l2))
ans=l1-l2-l;
else if(l>(l1+l2))
ans=l-l1-l2;
}
else
{
if(l<=l1+l2&&l>=l2-l1)
ans=0;
else if(l>l1+l2)
ans=l-l1-l2;
else
ans=l2-l1-l;
}
printf("%.8lf\n",ans);
}
return 0;
}
方法二AC:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int l1,l2,n;
double ans;
cin>>l1>>l2>>n;
double minl = abs(l1 - l2);
double maxl = abs(l2 + l1);
if(minl>maxl)
{
int temp=minl;
minl=maxl;
maxl=temp;
}
while(n--)
{
double x,y;
cin>>x>>y;
double l=sqrt(x*x+y*y);
if(l<=maxl&&l>=minl)
ans=0;
else if(l<minl)
ans=minl-l;
else if(l>maxl)
ans=l-maxl;
printf("%.8lf\n",ans);
}
return 0;
}
官方代码用到了一个hypotl函数,作用是求两个数平方和的平方根,相当于直接求到了距离,这是一个C函数库里的函数,再次受教了
#include <bits/stdc++.h>
using namespace std;
int l1, l2;
int main() {
int T;
scanf("%d%d%d", &l1, &l2, &T);
while (T--) {
double x, y;
scanf("%lf%lf", &x, &y);
long double dist = hypotl(x, y);
long double ans = 0;
if (dist > l1 + l2) ans = dist - l1 - l2;
if (dist < abs(l1 - l2)) ans = abs(l1 - l2) - dist;
printf("%.12Lf\n", ans);
}
return 0;
}
2、酷炫镜子
题目描述
小希拿到了一个镜子块,镜子块可以视为一个N x M的方格图,里面每个格子仅可能安装
\
或者
/
的镜子,会反射90°光线,也可能没有安装镜子,使用
.
代替。
但她看不清楚里面的镜子构造是怎样的。
你是这块镜子块的主人,所以你想计算这块镜子块(从输入的上方往下射入光线)从左到右每一格射入依次分别会从最下面的哪一格子射出,如果无法射出,输出-1。
输入描述:
第一行输入两个整数N,M。随后的N行,每行M个字符。
1≤N,M≤500
输出描述:
输出M行整数,依次为从第i个格子从上往下射入时从下面的哪里射出,如果光线不会从下面射出,则输出-1。
示例1
输入
3 3
…
…
.
输出
3
2
-1
说明
第一列遇到镜子两次反弹通过第三列射出。
第二列直接射出。
第三列因为镜子反弹后向右边射出。
其实这道题真的没有看起来那么麻烦,一个变相的搜索而已,区别一下方向,从不同方向遇见两种镜子分别会有不同的方向偏转,当行从下方到达地图外说明可以出去,当从其他位置到达地图外则说明不能出去,根据这个进行递归搜索就可以过了。
AC代码
#include<bits/stdc++.h>
using namespace std;
int M,N;
char Map[505][505];
void search_line(int x,int y,char dir)
{
if(x==M)
{
cout<<y+1<<endl;
return ;
}
if(x<0||y>=N||y<0)
{
cout<<"-1"<<endl;
return;
}
if(Map[x][y]=='.')
{
if(dir=='D')
search_line(x+1,y,dir);
else if(dir=='L')
search_line(x,y-1,dir);
else if(dir=='R')
search_line(x,y+1,dir);
else if(dir=='U')
search_line(x-1,y,dir);
}
if(Map[x][y]=='\\')
{
if(dir=='D')
search_line(x,y+1,'R');
else if(dir=='L')
search_line(x-1,y,'U');
else if(dir=='R')
search_line(x+1,y,'D');
else if(dir=='U')
search_line(x,y-1,'L');
}
if(Map[x][y]=='/')
{
if(dir=='D')
search_line(x,y-1,'L');
else if(dir=='L')
search_line(x+1,y,'D');
else if(dir=='R')
search_line(x-1,y,'U');
else if(dir=='U')
search_line(x,y+1,'R');
}
}
int main()
{
cin>>M>>N;
getchar();
for(int i=0;i<M;i++)
{
for(int j=0;j<N;j++)
cin>>Map[i][j];
getchar();
}
for(int i=0;i<N;i++)
search_line(0,i,'D');
return 0;
}
3、酷炫数学
题目描述
小希最近想知道一个东西,就是A+B=A|B(其中|为按位或)的二元组有多少个。
当然,直接做这个式子对小希来说太难了,所以小希改变了一些条件,她仅想知道其中A,B<N的情况,其中N为2的幂次。
当然,(A=1,B=0)和(A=0,B=1)被认为是不同的二元组。
输入描述:
第一行输入一个非负整数M。
N=2^M,M≤100
即2的M次为N。
输出描述:
一个整数ans,对998244353取模。
示例1
输入
输出
1
示例2
输入
71
输出
588378066
这是官方号称的签到题,更像是一个思维题,a+b什么时候等于a|b,题目其实给了暗示,把N化为二进制,只要二进制对应相加的位置在加之前为相异的即可,但是这样还是很抽象,可以采用笨办法就是写一下,写出来输入0,1,2的答案,对应答案为1,3,9,大胆尝试答案是等比为3的等比数列,直接求就可以了,还有一点需要注意的是数据量,需要取模,但是先算再取模会在计算过程中就溢出,所以在计算每一步的时候都取模一下,这样总量就不会溢出了。
AC代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int M;
cin>>M;
unsigned long long int ans=1;
for(int i=0;i<M;i++)
ans=ans*3 %998244353;
cout<<ans<<endl;
return 0;
}
4、酷炫数字
题目描述
小希希望你构造一个最小的正整数,使得其有n个因子。
输入描述:
第一行一个整数T表示数据组数
每组数据第一行输入一个正整数n,表示其因子数。
n≤1,000,000
T≤1,000,000
输出描述:
输出一行一个整数,表示你构造出的这个数。注意:你需要保证你构造的数≤1,000,000,如果在这个范围里面无法构造出一个正整数满足条件,请输出-1。
示例1
输入
2
4
5
输出
6
16
这个题比想象中简单不少,打表居然都可以过,需要用两层循环来统计因子数目,之后直接输出就好,难点在于这个打表,外层的i用于遍历每个数,内层的j则是遍历i所有在范围内的倍数,对于这些数,它们必然有i这个因子,如果构造的数字超出了范围就表示为0x3f。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 5;
int min_num[N], T, n;
int fact_count[N];
int main() {
memset(min_num, 0x3f, sizeof(min_num));
for (int i = 1; i <= 1000000; i++) {
for (int j = i; j <= 1000000; j += i) {
fact_count[j]++;
}
min_num[fact_count[i]] = min(min_num[fact_count[i]], i);
}
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
if (min_num[n] == 0x3f3f3f3f)
puts("-1");
else
printf("%d\n", min_num[n]);
}
return 0;
}