1. 程式人生 > >牛客小白月賽10 A,B,C,D題解

牛客小白月賽10 A,B,C,D題解

A 勘測:

題目:

傳送門A

思路:

找規律,通過找出前幾天的建設道路的次數發現為斐波那契額數列,然後求前n項的和即可。

程式碼如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=10000000007;
const int maxn=5*1e6+5;
int n;
ll a[maxn];
ll sum[maxn];
int main()
{
    scanf("%d",&n);
    memset(sum,0,sizeof(sum));
    a[0]=0;sum[0]=0;a[1]=1;a[2]=2;
    sum[1]=1;sum[2]=3;
    for (int i=3;i<=n;i++)
    {
        a[i]=(a[i-1]+a[i-2])%mod;
        sum[i]=(sum[i-1]+a[i])%mod;
    }
    printf("%lld\n",sum[n]%mod);
    return 0;
}

B 數學:

題目:

傳送門B

思路:

根據3,5,8,11倍數的特性來進行判定。

如果不知道倍數特性的話可以看看下面這篇部落格:

倍數特性

程式碼如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
string a;
int is[4];
int on[4]={3,5,8,11};
int num=0;
void Judge()
{
    int sum=0,sumo=0,sume=0,sum8=0;
    for (int i=0;i<a.length();i++)
    {
        sum+=a[i]-'0';
        if((i+1)%2)
            sumo+=a[i]-'0';
        else
            sume+=a[i]-'0';
    }
    if(sum%3==0)
        is[0]=1,num++;
    if(a[a.length()-1]=='0'||a[a.length()-1]=='5')
        is[1]=1,num++;
    for (int i=a.length()-1,j=0,k=1;i>=0&&j<3;i--,j++,k*=10)
        sum8=sum8+(a[i]-'0')*k;
    if(sum8%8==0)
        is[2]=1,num++;
    if(abs(sumo-sume)%11==0)
        is[3]=1,num++;
}
int main()
{
    cin>>a;
    memset (is,0,sizeof(is));
    Judge();
    if(num)
    {
        printf("Yes\n");
        for (int i=0;i<4;i++)
        {
            if(is[i])
            {
                printf("%d ",on[i]);
                num--;
            }
        }
        printf("\n");
    }
    else
    {
        printf("No\n");
    }
    return 0;
}

C 約數

題目:

傳送門C

思路:

求出a,b的gcd, 然後對gcd進行分解。

程式碼如下:
 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,b;
vector<ll>ans;
ll gcd (ll a,ll b)
{
    return b==0?a:gcd(b,a%b);
}
int main()
{
    scanf("%lld%lld",&a,&b);
    ll g=gcd(a,b);
    for (ll i=1;i<=sqrt(g);i++)
    {
        if(g%i==0)
        {
            ans.push_back(i);
            if(i*i!=g)
                ans.push_back(g/i);
        }
    }
    sort(ans.begin(),ans.end());
    for (int i=0;i<ans.size();i++)
    {
        printf("%lld%c",ans[i],i==ans.size()-1?'\n':' ');
    }
    return 0;
}

D 飢餓

題目:

傳送門D

思路:

將安全的道路建圖, 然後套用迪傑斯特拉演算法。

程式碼如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF=9223372036854775807;
const int maxn=1e6+5;
int head[maxn];
int n,m,s,t;
ll d[maxn];
struct edge
{
    int to;
    int next;
    ll len;
};
edge e[200005*4];
void addedge (int id,int u,int v,ll len)
{
     e[id].to=v;
     e[id].len=len;
     e[id].next=head[u];
     head[u]=id;
}
void djst()
{
    int vis[maxn];
    memset(vis,0,sizeof(vis));
    for (int i=0;i<=n;i++)
    {
        d[i]=INF;
    }
    d[s]=0;
    while (1)
    {
        ll Max=INF;
        int u=-1;
        for (int i=1;i<=n;i++)
        {
            if(!vis[i]&&Max>d[i])
            {
                Max=d[i];
                u=i;
            }
        }
        if(u==-1)
            break;
        vis[u]=1;
        for (int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            ll len=e[i].len;
            if(!vis[i]&&d[u]+len<d[v])
            {
                d[v]=d[u]+len;
            }
        }
    }
    if(d[t]==INF)
        printf("My gold!!!\n");
    else
        printf("%lld\n",d[t]);
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&s,&t);
    memset (head,-1,sizeof(head));
    for (int i=0,id=0;i<m;i++)
    {
        int flag,x,y;
        ll len;
        scanf("%d%d%d%lld",&flag,&x,&y,&len);
        if(flag)
        {
            addedge(id++,x,y,len);
            addedge(id++,y,x,len);
        }
    }
    djst();
    return 0;
}