伊蘇比的夢幻之旅(三)比賽題解

比賽地址:http://qscoj.cn/contest/25/c++

第9-1關 咒語轉換(小數據)算法

分析:將八進制轉換爲二進制,八進制只有一位,因此數據範圍只有0-7,直接手動轉換就行了。注意0-1是一位,2-3是兩位,4-7是三位。函數

標程:大數據

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin>>n;
    if (n==0) cout<<0<<endl;
    if (n==1) cout<<1<<endl;
    if (n==2) cout<<10<<endl;
    if (n==3) cout<<11<<endl;
    if (n==4) cout<<100<<endl;
    if (n==5) cout<<101<<endl;
    if (n==6) cout<<110<<endl;
    if (n==7) cout<<111<<endl;
    return 0;
}

第9-2關 咒語轉換(中數據)spa

分析:八進制長度最大爲17,因此能表示的最大的數爲8^17-1,在long long的範圍內,咱們能夠先考慮把八進制轉換成咱們熟悉的十進制,再把十進制轉換成二進制就很方便了。code

標程:blog

#include<bits/stdc++.h>
using namespace std;
long long ans,b[65];
int main()
{
    int i,len;
    long long j;
    bool flag;
    string s;
    cin>>s;len=s.length();
    ans=0;j=1;flag=false;
    for(i=len-1;i>=0;i--)
    {
        ans+=j*(s[i]-48);
        j*=8;
    }
    for(i=62;i>=0;i--)
    {
        j=(1ll<<i);
        b[i]=ans/j;ans%=j;
    }
    for(i=62;i>=0;i--)
    {
        if (b[i] || i==0) flag=true;
        if (flag) printf("%d",b[i]);
    }
    printf("\n");
    return 0;
}

第9-3關 咒語轉換(大數據)遊戲

分析:八進制數字的長度最大爲170000,不知道不少同窗是否是就想到了高精度呢?其實呀,根本不須要高精度。八進制轉二進制有個特色,就是8是2的3次方。因此,咱們能夠將八進制數以字符串的形式讀入,將一個數字拆成二進制的三個數字順序寫下來就好了,注意一下最高位轉換時要去掉前導0.ci

標程:字符串

#include<bits/stdc++.h>
using namespace std;
string s1[8]={"0","1","10","11","100","101","110","111"};
string s2[8]={"000","001","010","011","100","101","110","111"};
int main()
{
    string s;
    int i,len;
    cin>>s;len=s.length();
    cout<<s1[s[0]-48];
    for(i=1;i<len;i++)
        cout<<s2[s[i]-48];
    cout<<endl;
    return 0;
}

第10-1關 報數遊戲(小數據)

分析:小數據很是良心,都告訴了你x,y,z的值,因此直接手工計算都能得出答案\(^o^)/~

標程:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin>>n>>n>>n>>n;
    if (n==1) cout<<1<<endl;
    if (n==2) cout<<7<<endl;
    if (n==3) cout<<11<<endl;
    if (n==4) cout<<13<<endl;
    if (n==5) cout<<17<<endl;
    if (n==6) cout<<19<<endl;
    if (n==7) cout<<23<<endl;
    return 0;
}

第10-2關 報數遊戲(中數據)

分析:數據範圍爲10^7,其實只用for循環加上判斷直到找到第n個既不是x,又不是y,還不是z的倍數的數。事實證實,在x,y,z分別取2,3,5時所須要找的次數最多。根據容斥定理,1~q的數中大約有q/2+q/3+q/5-q/(2*3)-q/(3*5)-q/(2*5)+q/(2*3*5)=11q/15的數會是二、三、5的倍數,因此有約4q/11的數會被報到,而10^7除以4/11的答案也在O(n)算法複雜度接受的範圍內,故直接for循環掃一遍就好。

標程:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int a,b,c,n,i,cnt;
    scanf("%d%d%d%d",&a,&b,&c,&n);cnt=0;
    for(i=1;;i++)
    {
        if (i%a!=0 && i%b!=0 && i%c!=0) cnt++;
        if (cnt==n)
        {
            cout<<i<<endl;
            return 0;
        }
    }
}

第10-3關 報數遊戲(大數據)

分析:根據第10-2關的相關分析,咱們能夠經過容斥定理計算出1-q之間有多少個數會被報到(不是x,y,z任何一個數的倍數),直接計算不是其倍數的數很差計算。能夠計算出是x,y,z中一個數的倍數的數的個數。計算公式爲S=q/x+q/y+q/z-q/gcd(x,y)-q/gcd(y,z)-q/gcd(z,x)+q/gcd(x,y,z);q-S就是報到的數。而後咱們能夠經過二分的方式找出最先報出N個數的q值,就是本題的答案。注意x,y,z均爲10^7,直接乘會爆long long,就得用相除的方式判斷一下gcd(x,y,z)是否比10^18大,若是比他大的話就不用管它了。

標程:

#include<bits/stdc++.h>
using namespace std;
long long gcd(long long a,long long b)
{
    return b==0?a:gcd(b,a%b);
}
long long lcm(long long a,long long b)
{
    long long ans,k;
    ans=a/gcd(a,b);k=1e18/ans;
    if (k<b) ans=-1;
    else ans*=b;
    return ans;
}
int main()
{
    long long l,r,x,y,z,n,m,ans;
    long long xy,yz,zx,xyz;
    cin>>x>>y>>z>>n;
    l=0;r=1e18;
    while(l+1<r)
    {
        m=(l+r)/2;
        ans=m/x+m/y+m/z;
        xy=lcm(x,y);
        yz=lcm(y,z);
        zx=lcm(z,x);
        ans-=(m/xy+m/yz+m/zx);
        xyz=lcm(xy,z);
        if (xyz!=-1) ans+=m/xyz;
        if (m-ans>=n) r=m;
        else l=m;
    }
    cout<<r<<endl;
    return 0;
}

第11-1關 將來世界(小數據)

分析:數據範圍只有1-17,N天后都不會超出這個月,直接輸出2017,5,14+N就行了。

標程:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin>>n;
    cout<<"2017 5 "<<n+14<<endl;
    return 0;
}

第11-2關 將來世界(中數據)

分析:數據範圍爲10^7,因此能夠直接日後枚舉就好。個人方法是將閏年和平年每月的日期儲存起來,而後日期到32就變爲1,並給月份加1;月份到13就變1,並給年份加1.而後再判斷這個日期合不合法,合法的話就給計數器加1,計數器到N的時候就輸出這個日期。

標程:

#include<bits/stdc++.h>
using namespace std;
int run[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
int ping[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool leap(int y)
{
    if (y%400==0) return true;
    if (y%4==0 && y%100!=0) return true;
    return false;
}
int main()
{
    int y,m,d,n,cnt;
    scanf("%d",&n);
    y=2017;m=5;d=14;cnt=0;
    while(cnt<n)
    {
        d++;
        if (d==32) {d=1;m++;}
        if (m==13) {m=1;y++;}
        if (leap(y))
        {
            if (d<=run[m]) cnt++;
        }
        else
        {
            if (d<=ping[m]) cnt++;
        }
    }
    cout<<y<<" "<<m<<" "<<d<<endl;
    return 0;
}

第11-3關 將來世界(大數據)

分析:數據範圍爲10^17,直接for確定超時。可是,每一年的天數不徹底同樣,每4年的天數也不都徹底同樣。所以,不少同窗可能以爲難如下手。但實際上,這確定是有規律的。根據閏年的定義,咱們知道每400年固定會有97個閏年,所以每400年的天數是固定不變的,爲365*400+97=146097天,因此咱們先對這個天數取模,看這個天數包含多少個400年,再把剩餘的天數按照第11-2關的方法暴力跑一下就能夠肯定月和日,最後再在年份上加上前面的商乘上400的值就是正確答案了。

標程:

#include<bits/stdc++.h>
using namespace std;
int run[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
int ping[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool leap(int y)
{
    if (y%400==0) return true;
    if (y%4==0 && y%100!=0) return true;
    return false;
}
int main()
{
    int m,d,cnt;
    long long n,y,x;
    scanf("%lld",&n);x=n/146097;n%=146097;
    y=2017;m=5;d=14;cnt=0;
    while(cnt<n)
    {
        d++;
        if (d==32) {d=1;m++;}
        if (m==13) {m=1;y++;}
        if (leap(y))
        {
            if (d<=run[m]) cnt++;
        }
        else
        {
            if (d<=ping[m]) cnt++;
        }
    }
    y+=400*x;
    cout<<y<<" "<<m<<" "<<d<<endl;
    return 0;
}

第12關 萬物皆空

分析:本題純屬娛樂,根據題目的意思,沒有任何輸入輸出,把頭文件和主函數打一下就行了。

標程:

#include<stdio.h> 
int main(){}
相關文章
相關標籤/搜索