牛客小白月賽21全解


題目鏈接:https://ac.nowcoder.com/acm/contest/3947#question

emmm,小白賽,G題手賤,送了4發,出了8題,B,D沒有出來(rank 59)

題目說明:

A.三角形外心求解 B.大模擬 C.前綴和思想
D.記憶化搜索或拓撲排序 E.水題 F.斐波那契數列性質
G.數論+思維 H.水題 I.子序列DP

J.三維BFS

 

 

 

 

 

 

 

 

A-Audio:

題目大意:給你3個點的坐標,讓你找到一個點使得該點的到3點的距離一樣。給個樣例:

Input:

0 0
1 3
4 2

Output:

2.000 1.000

 

 

 

 

 

 

 

emmm,三點不在一條直線上,則可構成三角形,那么三角形的外心到三點的距離是一樣的,然后套個三角形外心的公式就OK了,

具體求解過程:https://blog.csdn.net/u010141928/article/details/88942989

以下是AC代碼:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    double x1,y1,x2,y2,x3,y3;
    double a,b,c,p;
    double  aa,bb,zz,aa1,bb1,zz1;
    scanf("%lf%lf",&x1,&y1);
    scanf("%lf%lf",&x2,&y2);
    scanf("%lf%lf",&x3,&y3);
    aa=2*(x1-x2);
    bb=2*(y1-y2);
    zz=x1*x1-x2*x2+y1*y1-y2*y2;
    aa1=2*(x3-x2);
    bb1=2*(y3-y2);
    zz1=x3*x3-x2*x2+y3*y3-y2*y2;
    printf("%.3lf %.3lf\n",((zz*bb1)-(zz1*bb))/((aa*bb1)-(aa1*bb)),
           ((aa*zz1)-(aa1*zz))/((aa*bb1)-(aa1*bb)));
    return 0;
}
View Code

 

B-Bits:

題目大意:給你圓盤的個數n,求漢諾塔的移動過程,並將其繪制出來,如果n是奇數則移動到中間的柱子,否則就移動到最右邊的柱子上。給個樣例:

Input:

2

Output:

...................
...|.....|.....|...
..***....|.....|...
.*****...|.....|...
-------------------
...................
...|.....|.....|...
...|.....|.....|...
.*****..***....|...
-------------------
...................
...|.....|.....|...
...|.....|.....|...
...|....***..*****.
-------------------
...................
...|.....|.....|...
...|.....|....***..
...|.....|...*****.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

emmm,外觀上有點問題,只不過在屏幕上每個字符大小是一樣的就很整齊了。

我們先移動盤子,不考慮畫圖,那么程序很好寫,當n為奇數的時候,我們將第二個柱子當做第三柱子進去就好了:

void move(int n,int a,int b,int c)
{
    if (n==1) {solve(a,c);return;}
    move(n-1,a,c,b);
    solve(a,c);//將a移動到c
    move(n-1,b,a,c);
}

int main()
{
    int n;
    scanf ("%d",&n);
    sum=n;
    int a=1,b=2,c=3;
    move(n,a,b,c);
    return 0;
}
View Code

接下來就是畫圖了。。。這就是個純粹的大模擬,不過為了簡化它,我們可以將每層分為三個部分,然后找到柱子的位置和盤子的范圍。

以下是AC代碼:

#include <bits/stdc++.h>
using namespace std;

vector<int>g[10];
int sum,tot;
char pan='*',zhu='|',kong='.',ge='-';

void print()
{
    tot--;
    int n=sum;
    int len=3*(2*sum+1)+4;
    for (int i=1; i<=len; i++) printf ("%c",kong);printf ("\n");
    for (int i=1; i<=3; i++){
        printf("%c",kong);
        int round=(2*sum+1)/2+1;
        for (int j=1; j<=sum*2+1; j++)
            if (j==round) printf("%c",zhu);
            else printf("%c",kong);
    }
    printf("%c\n",kong);
    for (int i=n; i>=1; i--){//第幾層
        for (int j=1; j<=3; j++){//第幾個柱子
            printf("%c",kong);
            int h=g[j].size();
            int round=(2*sum+1)/2+1;//柱子的位置
            for (int k=1; k<=2*sum+1; k++){//每個柱子管轄的范圍
                if (h<i){
                    if (k==round) printf("%c",zhu);
                    else printf("%c",kong);
                }
                else {
                    int length=g[j][i-1];
                    int l=round-length,r=round+length;//盤子的范圍
                    if (k>=l && k<=r) printf("%c",pan);
                    else printf("%c",kong);
                }
            }
        }
        printf("%c\n",kong);
    }
    if (tot==0) return;
    for (int i=1; i<=len; i++) printf ("%c",ge);printf("\n");
}

void solve(int a,int b)
{
    int p=g[a].size()-1;
    g[b].push_back(g[a][p]);
    g[a].erase(g[a].begin()+p);
    print();
}

void move1(int n,int a,int b,int c)
{
    if (n==1) {solve(a,c);return;}
    move1(n-1,a,c,b);
    solve(a,c);
    move1(n-1,b,a,c);
}

int main()
{
    int n;
    scanf ("%d",&n);
    sum=n;
    tot=1;
    for (int i=1; i<=n; i++) tot*=2;
    for (int i=n; i>=1; i--) g[1].push_back(i);
    int a=1,b=2,c=3;
    print();
    if ((n%2)==0) move1(n,a,b,c);
    else move1(n,a,c,b);
    return 0;
}
View Code

 

C-Channels:

題目大意:給你一個區間讓你求有多少時間是在看劇。其中電視在時刻1開始到無窮,每50分鍾后有10分鍾的廣告。給個樣例:

Input:

1 61

Output:

51

 

 

 

 

 

emmm,就是利用一下前綴和的思想,我們用sum[r]-sum[l-1]就完事了。我們直接除60,然后再減一下,剩下的就是個不完整的時間,如果這個時間>50,那么就增加廣告時間。

以下是AC代碼:

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

#define ll long long

int main(){
    ll t1,t2;
    while (~scanf ("%lld%lld",&t1,&t2)){
        t1--;
        ll sum1=t1/60;
        ll p1=t1-sum1*60;
        if (p1>50) sum1=sum1*10+p1-50;
        else sum1*=10;
        ll ans1=t1-sum1;
        ll sum2=t2/60;
        ll p2=t2-sum2*60;
        if (p2>50) sum2=sum2*10+p2-50;
        else sum2*=10;
        ll ans2=t2-sum2;
        printf ("%lld\n",ans2-ans1);
    }
    return 0;
}
View Code

 

D-DDOoS:

題目大意:給你一張有向圖,讓你求從1到n有多少條不同的路徑。給個樣例:

Input:

4 4
1 2 3
1 3 1
2 4 1
3 4 3

Output:

2

 

 

 

 

 

 

 

 

emmm,記憶化搜索,當時題目讀錯了,以為是最短路徑數。。。

以下是AC代碼:

#include <bits/stdc++.h>
using namespace std;

const int N=1e5+10;
const int M=2e5+10;
const int mod=20010905;

int head[N],ans[N],vis[N],num=0;
struct node
{
    int to,next,w;
}eg[M<<1];

void add(int u,int v,int w)
{
    eg[++num]=node{v,head[u],w};
    head[u]=num;
}

int dfs(int x,int ed)
{
    if (x==ed) return 1;
    if (ans[x]) return ans[x];
    for (int i=head[x]; i!=-1; i=eg[i].next){
        int v=eg[i].to;
        ans[x]=(ans[x]+dfs(v,ed))%mod;
    }
    return ans[x]%mod;
}

int main()
{
    int n,m;
    scanf ("%d%d",&n,&m);
    memset(head,-1,sizeof head);
    for (int i=1; i<=m; i++){
        int u,v,w;
        scanf ("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    printf ("%d\n",dfs(1,n));
    return 0;
}
View Code

 

E-Exams:

題目大意:emmm,就是個純粹的計算題。樣例:

Input:

5
0 1 97 1 0 0 0 0
0 2.5 98 0.3 0 0 92 0.7
0 4 100 0.3 0 0 100 0.7
0 1 0 0 0 0 74 1
0 2 94 1 0 0 0 0

Output:

94.67

 

 

 

 

 

 

 

 

 

 

以下是AC代碼:

#include <bits/stdc++.h>
using namespace std;
 
int main()
{
    int n;
    cin>>n;
    double ans=0,sum=0;
    for (int i=1; i<=n; i++){
        int id;
        double pt,c1,p1,qz,p2,qm,p3;
        cin>>id>>pt>>c1>>p1>>qz>>p2>>qm>>p3;
        if (id==2) continue;
        double grd=c1*p1+qz*p2+qm*p3;
        grd*=10;
        int s=(int)grd;
        if (s%10>=5) s+=10;
        s/=10;
        ans+=s*pt;
        sum+=pt;
    }
    ans/=sum;
    printf ("%.2f\n",ans);
    return 0;
}
View Code

 

F-Fool Problem:

題目大意:給你n,讓你求$f_{n+1}f_{n-1}-f_{n}^{2}$其中$f$是斐波那契數列。樣例:

Input:

2

Output:

1          

 

 

 

 

 

就是利用斐波那契數列的性質,具體的性質:https://www.cnblogs.com/Milkor/p/4734763.html

以下是AC代碼:

#include <cstdio>
#include <cstring>
using namespace std;

const int mac=3e3+10;

char s[mac];

int main()
{
    scanf ("%s",s);
    int len=strlen(s);
    int p=s[len-1]-'0';
    if (!(p%2)) printf ("1\n");
    else printf ("-1\n");
    return 0;
}
View Code

 

G-Game:

題目大意:給你一個數n,Nancy和Johnson先后將其拆解為兩個任意兩個非1因子的積,問誰最后無法操作。樣例:

Input:

4

Output:

Johnson

 

 

 

 

 

實際上這題就是問n的質因子的個數,如果個數為奇數,那么就是就是Nancy輸掉,但我們要特判一下n是否為質數或者1。

至於為什么,除最后一次拆解外,每次拆解得到一個質數和一個合數,我們看看它可以拆解多少次就好了

以下是AC代碼:

#include <bits/stdc++.h>
using namespace std;
 
const int mac=1e5+10;
 
int vis[mac],prim[mac];
int nb;
 
int main()
{
    int n,cnt=0;
    scanf ("%d",&n);
    int m=sqrt(n);
    for (int i=2; i<=m; i++)
        if (!vis[i])
            for (int j=i*i; j<=n; j+=i) vis[j]=1;
    for (int i=2; i<=n; i++)
        if (!vis[i]) prim[++cnt]=i;
    m=n;
    for (int i=1; i<=cnt; i++){
        while (n%prim[i]==0 && m!=prim[i]) nb++,n/=prim[i];
    }
    n=m;
    if (!vis[n]) printf ("Nancy\n");
    else if (nb%2) printf ("Nancy\n");
    else if (!(nb%2)) printf ("Johnson\n");
    return 0;
}
View Code

 

H-"Happy New Yeay!":

題目大意:輸出題目

注意連引號也要輸出,用一下轉義字符就好了,同時不能直接復制,它是中文的引號當時。

以下是AC代碼:

#include <cstdio>
int main()
{
    printf ("\"Happy New Year!\"\n");
    return 0;
}
View Code

 

I-I Iove you:

題目大意:給你一個字符串,讓你求iloveyou作為子序列出現了多少次,大小寫不區分。對20010905取模。樣例:

Input:

IloveyouNotonlyforwhatyouareButforwhatIamWhenIamwithyouIloveyouNotonlyforwhatYouhavemadeofyourselfButforwhatYouaremakingofme

Output:

2864

 

 

 

 

emmm,是個dp。令 $f[i][j],(j = 1...8)$ 表示前 i 個字符中,匹配了字符串”iloveyou” 的前多少位,那么有轉移方程:

$f[i][j] = (f[i−1][j] + (s[i] ==ss[j])∗f[i−1][j]) % mod$

當然,$f[i][1]$比較特殊:$f[i][1] = (f[i−1][1] + (s[i] ==′ i′)) % mod$

以下是AC代碼:

#include <bits/stdc++.h>
using namespace std;

#define ll long long

const int mac=1e6+10;
const int mod=20010905;

ll dp[10];

int main(){
    string s;
    cin>>s;
    string m="iloveyou";
    for(int i=0;i<s.length();i++){
        s[i]=tolower(s[i]);  
        for (int j=8; j>=1; j--){
            if (j==1) dp[j]=(dp[j]+(s[i]==m[j-1]))%mod;
            else dp[j]=(dp[j]+(s[i]==m[j-1])*dp[j-1])%mod;
        }
    }
    cout<<dp[8]<<endl;
    return 0;
}
View Code

 

J-Jelly:

題目大意:從(1,1,1)到(n,n,n)至少需要多少時間,n層,每層n行n列。樣例:

Input:

2
.*
..
*.
..

Output:

4

 

 

 

 

 

 

 

 

實際上就是個三維的BFS,和POJ2251一樣。這里注意特判一下n等於1的情況就好了,然后注意起點入隊的時候放入的時間是1。

#include <cstdio>
#include <cstring>
#include <queue>
#define BYJ(cx,cy,cl,cen,n,m) (cx>=1)&&(cx<=n)&&(cy>=1)&&(cy<=m)&&(cl>=1)&&(cl<=cen)
using namespace std;
const int mac=110;
int dre[6][3]={{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}};  //{x,y,z的走向}
int a[mac][mac][mac],v[mac][mac][mac];
int main() {
    int cen,n,m;
    while (~scanf ("%d",&n)) {
        cen=m=n;
        memset(a,0,sizeof(a));
        memset(v,0,sizeof(v));
        queue<int>qx,qy,ql,stp;     
        int sx,sy,sc,fx,fy,fc,mark=0;
        for (int k=1; k<=cen; k++)
            for (int i=1; i<=n; i++)
                for (int j=1; j<=m; j++) {
                    char ch=getchar();
                    while (ch!='.' && ch!='*') ch=getchar();
                    if (ch=='*') a[k][i][j]=1;
                }
        if (n==1) {printf ("1\n");return 0;}
        sx=sy=sc=1;
        fx=fy=fc=n;
        qx.push(sx),qy.push(sy),ql.push(sc),stp.push(1);//注意剛開始是1
        v[sc][sx][sy]=1;
        while (!qx.empty()) {
            if (mark) break;   
            for (int i=0; i<6; i++) {    //六種方向入隊
                    int cx,cy,cl;
                    cx=qx.front()+dre[i][0];   
                    cy=qy.front()+dre[i][1];
                    cl=ql.front()+dre[i][2];    //層數
                if (BYJ(cx,cy,cl,cen,n,m) && !a[cl][cx][cy] && !v[cl][cx][cy]) {
                    if (cx==fx && cy==fy && cl==fc) {
                        printf ("%d\n",stp.front()+1);
                        mark=1;break;            
                    }
                    v[cl][cx][cy]=1;
                    qx.push(cx),qy.push(cy),ql.push(cl),stp.push(stp.front()+1);
                }
            }
            if (mark) break;
            qx.pop(),qy.pop(),ql.pop(),stp.pop();
        }
        if (!mark) printf ("-1\n");
    }
    return 0;
}
View Code


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM