曆史性突破,第一次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;
}