寒假牛客第五場

A-炫酷雙截棍
 

題目描述

小希現在手裏有一個連着的兩塊木條,長度分別爲l1l1,l2l2,木條之間有一個無摩擦的連接點,木條之間可以相互轉動,小希將其稱之爲雙截棍。

現在小希把長爲l1l1的木條的一端放在原點(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

簽到題,只需判斷原點到給出點的距離比兩個棍的長度的和大或者比兩個棍的長度的差小,就不能達到,否則就可以。

#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI  acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x)  priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
double l1,l2,ans;
int main()
{
    while(~scanf("%lf%lf",&l1,&l2)){
        int t;
        sc(t);
        double x,y;
        while(t--){
            scanf("%lf%lf",&x,&y);
            double sum=sqrt(x*x+y*y);
            if(sum>l1+l2)
                printf("%.8f\n",sum-l1-l2);
            else if(sum<abs(l1-l2))
                printf("%.8f\n",abs(l1-l2)-sum);
            else printf("0.00000000\n");
        }
    }
}

D-炫酷路途

題目描述

小希現在要從寢室趕到機房,路途可以按距離分爲N段,第i個和i+1個是直接相連的,只需要一秒鐘就可以相互到達。

炫酷的是,從第i個到第i+2pi+2p個也是直接相連的(其中p爲任意非負整數),只需要一秒鐘就可以相互到達。

更炫酷的是,有K個傳送法陣使得某些u,v之間也是直接相連的,只需要一秒鐘就可以相互到達,當然,由於設備故障,可能會有一些u=v的情況發生。

現在小希爲了趕路,她需要在最短的時間裏從寢室(編號爲1)到達機房(編號爲N),她不希望到達這N個部分以外的地方(不能到達位置N+1),也不能走到比自己當前位置編號小的地方(比如從5走到3是非法的)。

她想知道最短的時間是多少。

輸入描述:

第一行輸入兩個整數N,K,表示路途的段數和傳送法陣的數量。

從第二行開始K行,每行兩個整數aiai,bibi表示兩個位置之間相連。
2≤N≤1,000,000,0002≤N≤1,000,000,000

0≤K≤150≤K≤15

輸出描述:

輸出一個整數,表示從寢室到機房最短的時間是多少秒。

示例1

輸入

複製

12 2
1 5
6 6

輸出

複製

3

示例2

輸入

複製

17 2
2 5
8 9

輸出

複製

1

這個題讓我明白了二進制還可以這麼用......之前二進制接觸的太少了。

1e9的範圍,也就2的30多次方,如果不用傳送陣,也就是說走30多步即可到達。

那具體的怎麼求呢?

把兩個點的距離轉換成二進制,二進制中有幾個1就需要走幾步,因爲可以一下走2的次方的距離,所以二進制有幾個1就說明要走多少步。可以用lowbit(x)來求,就是x & -x,求的是x中最低位的1,例如:6(110),lowbit(6)=2=2^1,上次用到lowbit還是在學樹狀數組的時候......

如果用傳送陣,K<=15,最多的情況也就是2^15種情況,可以枚舉出來,從0到2^15依次是不用傳送陣,用第一個,用第二個,用第一個和第二個......

具體看代碼

#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI  acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x)  priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
const int N=1e9+10;
int n,k;
struct node
{
    int u;
    int v;
}p[20];
int step(int x)
{
    int ans=0;
    while(x){
        x-=lowbit(x);
        ans++;
    }
    return ans;
}
bool cmp(node x,node y)
{
    return x.u<y.u;
}
int main()
{
    while(~scanf("%d%d",&n,&k)){
        for(int i=0;i<k;i++)
            scanf("%d%d",&p[i].u,&p[i].v);
        sort(p,p+k,cmp);
        int ans=step(n-1);
        for(int i=0;i<1<<k;i++){  //這裏就是那最多2^15次的情況,
              int t=1,sum=0;
            for(int j=0;j<k;j++)  { //這裏是枚舉每個傳送陣
                if(i&j<<k){           //i&1<<j 的意思是在這第i種情況下是否要用第j個傳送陣
                    if(t>p[j].u)
                        continue;
                    sum+=step(p[j].u-t)+1;
                    t=p[j].v;
                }
            }
            if(t>n)
                continue;
                sum+=step(n-t);
            ans=min(ans,sum);
        }
        printf("%d\n",ans);
    }
}

G-炫酷數字

題目描述

小希希望你構造一個最小的正整數,使得其有n個因子。

輸入描述:

第一行一個整數T表示數據組數

每組數據第一行輸入一個正整數n,表示其因子數。

n≤1,000,000n≤1,000,000

T≤1,000,000T≤1,000,000

輸出描述:

輸出一行一個整數,表示你構造出的這個數。注意:你需要保證你構造的數≤1,000,000≤1,000,000,如果在這個範圍裏面無法構造出一個正整數滿足條件,請輸出-1。

示例1

輸入

複製

2
4
5

輸出

複製

6
16

這個想到了質數唯一分解定理,然後就T了。。。

原來可以先把1e6次方的範圍內的數的因子數先預處理出來,直接查詢即可...orz

#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI  acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x)  priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
const int N=1e6+10;
int num[N],vis[N];
void init()         //預處理
{
    for(int i=1;i<N;i++){
    for(int j=i;j<N;j+=i)
        num[j]++;
        if(!vis[num[i]])     //vis數組用來求最小的M
            vis[num[i]]=i;
    }
}
int main()
{
    met(vis,0);
    met(num,0);
    init();
    int n,t;
    sc(t);
    while(t--){
        sc(n);
        if(!vis[n])
            printf("-1\n");
        else printf("%d\n",vis[n]);
    }
}

I-炫酷鏡子

鏈接:https://ac.nowcoder.com/acm/contest/331/I
來源:牛客網
 

題目描述

小希拿到了一個鏡子塊,鏡子塊可以視爲一個N x M的方格圖,裏面每個格子僅可能安裝`\`或者`/`的鏡子,會反射90°光線,也可能沒有安裝鏡子,使用`.`代替。

但她看不清楚裏面的鏡子構造是怎樣的。

你是這塊鏡子塊的主人,所以你想計算這塊鏡子塊(從輸入的上方往下射入光線)從左到右每一格射入依次分別會從最下面的哪一格子射出,如果無法射出,輸出-1。

輸入描述:

第一行輸入兩個整數N,M。隨後的N行,每行M個字符。

1≤N,M≤5001≤N,M≤500

輸出描述:

輸出M行整數,依次爲從第i個格子從上往下射入時從下面的哪裏射出,如果光線不會從下面射出,則輸出-1。

示例1

輸入

複製

3 3
...
...
\.\

輸出

複製

3
2
-1

說明

第一列遇到鏡子兩次反彈通過第三列射出。

第二列直接射出。

第三列因爲鏡子反彈後向右邊射出。

就是個模擬,可能細節多一點

#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI  acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x)  priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
int n,m;
char a[505][505];
void dfs(int x,int y,int z)  //x,y爲座標,z代表方向,1指從上往下,2:從下往上,3:從左往右,4:從右向左
{
    if(x>n){
        printf("%d\n",y);
        return ;
    }
    else if(x<1||y<1||y>m){
        printf("-1\n");
        return ;
    }
    if(z==1){
            int i;
    for(i=x;i<=n;i++){
        if(a[i][y]=='.')
            continue;
        else if(a[i][y]=='/'){
                if(y==1){
                    printf("-1\n");
                    break;
                }
            dfs(i,y-1,4);
            break;
        }
        else{
                if(y==m){
                    printf("-1\n");
                    break;
                }
                dfs(i,y+1,3);
                break;
            }
    }
    if(i==n+1&&a[n][y]=='.'){
    printf("%d\n",y);
    return ;
    }
}
    else if(z==2){
            int i;
        for(i=x;i>=1;i--){
            if(a[i][y]=='.')
            continue;
          else if(a[i][y]=='/'){
                if(y==m){
                    printf("-1\n");
                    break;
                }
            dfs(i,y+1,3);
            break;
          }
          else {
                if(y==1){
                    printf("-1\n");
                    break;
                }
            dfs(i,y-1,4);
            break;
          }
        }
        if(i==0&&a[1][y]=='.'){
            printf("-1\n");
            return ;
        }
    }
    else if(z==3){
        int i;
        for(i=y;i<=m;i++){
            if(a[x][i]=='.')
                continue;
            else if(a[x][i]=='/'){
                    if(x==1){
                        printf("-1\n");
                        break;
                    }
                dfs(x-1,i,2);
                break;
            }
            else {
                    if(x==n){
                        printf("%d\n",i);
                        break;
                    }
                dfs(x+1,i,1);
                break;
            }
        }
        if(i==m+1&&a[x][m]=='.'){
            printf("-1\n");
            return ;
        }
    }
    else {
        int i;
        for(i=y;i>=1;i--){
            if(a[x][i]=='.')
                continue;
            else if(a[x][i]=='/'){
                    if(x==n){
                        printf("%d\n",i);
                        break;
                    }
                dfs(x+1,i,1);
                break;
            }
            else {
                    if(y==1){
                        printf("-1\n");
                        break;
                    }
                dfs(x-1,i,2);
                break;
            }
        }
        if(i==0&&a[x][1]=='.'){
            printf("-1\n");
            return ;
        }
    }
}
int main()
{
    while(cin>>n>>m){
            char c=getchar();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            cin>>a[i][j];
        for(int i=1;i<=m;i++){
            dfs(1,i,1);
        }
    }
}

J-炫酷數學

鏈接:https://ac.nowcoder.com/acm/contest/331/J
來源:牛客網
 

題目描述

小希最近想知道一個東西,就是A+B=A|B(其中|爲按位或)的二元組有多少個。

當然,直接做這個式子對小希來說太難了,所以小希改變了一些條件,她僅想知道其中A,B<NA,B<N的情況,其中N爲2的冪次。

當然,(A=1,B=0)和(A=0,B=1)被認爲是不同的二元組。

輸入描述:

第一行輸入一個非負整數M。

N=2M,M≤100N=2M,M≤100

 

即2的M次爲N。

輸出描述:

一個整數ans,對998244353取模。

示例1

輸入

複製

0

輸出

複製

1

示例2

輸入

複製

71

輸出

複製

588378066

其實打個表,很容易發現答案其實就是3^m。

如果不是找規律,也可以發現二進制中,每一位只有00,01,10三種情況,2^m次方,就是二進制一共有m位,也就是3^m次方

#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI  acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x)  priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
const int mod=998244353;
int m;
ll ksm(ll j,ll k,ll l)
{
    long long ans=1;
    j%=l;
    while(k){
        if(k&1)
            ans=(ans*j)%l;
        j=(j*j)%l;
        k>>=1;
    }
    return ans;
}
int main()
{
    while(~scanf("%d",&m)){
        ll ans=ksm(3,m,mod);
            printf("%lld\n",ans);
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章