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

比賽地址:http://qscoj.cn/contest/20/java

第1-1關 教練(小數據)c++

分析:a,b只有10^4大小,典型水題,直接計算兩個教練的訓練效果值再進行比較就好。大數據

標程:ui

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int a,b,p1,p2;
    cin>>a>>b;
    p1=a+b;p2=a*b;
    if (p1>p2) cout<<1<<endl;
    if (p1==p2) cout<<"1/2"<<endl;
    if (p1<p2) cout<<2<<endl;
    return 0;
}

第1-2關 教練(中數據)spa

分析:a,b有10^18大小,相乘的話會爆long long,比較結果會產生錯誤。仔細分析一下咱們不難判斷,若是a和b中有一個爲1,假設a爲1,那麼教練1的訓練效果值p1=1+b,教練2的訓練效果值p2=1*b=b,不管b爲多少,p1總大於p2;若是a,b中最小值爲2,假設a爲2,p1=2+b,p2=2*b=2b,b>=2時2+b<=2b,只有當b=2時才取等號;若是a,b中最小值大於等於3時,a+b始終會小於a*b,因此只用對a,b進行一下判斷就好。code

標程:blog

#include<bits/stdc++.h>
using namespace std;
int main()
{
    long long a,b;
    cin>>a>>b;
    if (a==1 || b==1) cout<<1<<endl;
    else
        if (a==2 && b==2) cout<<"1/2"<<endl;
        else cout<<2<<endl;
    return 0;
}

第1-3關 教練(大數據)ip

分析:由第1-2關咱們分析出,只須要對a,b的值進行判斷就好,但這裏a,b的範圍爲10^418,因此得用字符串的方式進行輸入並判斷。ci

標程:字符串

#include<bits/stdc++.h>
using namespace std;
int main()
{
    string a,b;
    cin>>a>>b;
    if (a=="1" || b=="1") cout<<1<<endl;
    else
        if (a=="2" && b=="2") cout<<"1/2"<<endl;
        else cout<<2<<endl;
    return 0;
}

第2-1關 魔方(小數據)

分析:購買2-5階魔方各一個,數出每一個魔方的中心塊數、棱塊數和角塊數就好。

標程:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin>>n;
    if (n==2) printf("0\n0\n8\n");
    if (n==3) printf("6\n12\n8\n");
    if (n==4) printf("24\n24\n8\n");
    if (n==5) printf("54\n36\n8\n");
    return 0;
}

第2-2關 魔方(中數據)

分析:一個魔方有6個面,N階魔方每一個面的中心塊是一個矩形,其邊長爲N-2,因此中心塊的數量爲6*(N-2)*(N-2);一個N階魔方的立方體有12條棱,每條棱的長度爲N-2,因此棱塊的數量爲12*(N-2);而無論魔方的階數爲多少,其角塊數量均爲8。N的範圍爲10^9,其最大計算值不會超過10^18,用long long儲存就好。

標程:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    long long n;
    cin>>n;
    cout<<6*(n-2)*(n-2)<<endl;
    cout<<12*(n-2)<<endl;
    cout<<8<<endl;
    return 0;
}

第2-3關 魔方(大數據)

分析:由第2-2關咱們知道一個N階魔方的中心塊數、棱塊數和角塊數分別爲6*(N-2)*(N-2)、12*(N-2)、8。可是N的範圍高達10^5109,因此得考慮使用高精度。固然,若是你會JAVA的話用BigInteger這個問題就很好解決了。

C++標程:

#include<bits/stdc++.h>
using namespace std;
int a[12000],b[12000],z[12000],l[12000];
int main()
{
    string s;
    int len,i,j;
    bool flag;
    cin>>s;len=s.length();
    for(i=0;i<len;i++)
    {
        a[i]=s[len-1-i]-48;
        b[i]=a[i];
    }
    b[0]-=2;j=0;
    while(b[j]<0)
    {
        b[j]+=10;j++;b[j]--;
    }
    for(i=0;i<len;i++)
        l[i]=b[i]*12;
    for(i=0;i<len+2;i++)
    {
        j=l[i]/10;l[i]%=10;l[i+1]+=j;
    }
    for(i=0;i<len;i++)
     for(j=0;j<len;j++)
        z[i+j]+=b[i]*b[j];
    for(i=0;i<2*len;i++)
        z[i]*=6;
    for(i=0;i<2*len;i++)
    {
        j=z[i]/10;z[i]%=10;z[i+1]+=j;
    }
    flag=false;
    for(i=11111;i>=0;i--)
    {
        if (i==0 || z[i]) flag=true;
        if (flag) printf("%d",z[i]);
    }
    printf("\n");
    flag=false;
    for(i=11111;i>=0;i--)
    {
        if (i==0 || l[i]) flag=true;
        if (flag) printf("%d",l[i]);
    }
    printf("\n");
    cout<<8<<endl;
    return 0;
}

JAVA標程:

import java.util.*;
import java.math.*;
public class Main{
    public static void main(String agrs[]){
        Scanner cin=new Scanner(System.in);
        BigInteger a,b,c,d;
        a=cin.nextBigInteger();
        b=a.subtract(BigInteger.valueOf(2));
        c=b.multiply(b);
        c=c.multiply(BigInteger.valueOf(6));
        d=b.multiply(BigInteger.valueOf(12));
        System.out.println(c);
        System.out.println(d);
        System.out.println(8);
    }
}

第3-1關 迴文數(小數據)

分析:L,R的數據範圍只有1-13,咱們均可以手算出其中的迴文數:一、二、三、四、五、六、七、八、九、11,因此直接for一遍統計答案就好。

標程:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int l,r,i,cnt;
    cin>>l>>r;cnt=0;
    for(i=l;i<=r;i++)
        if (i<=9 || i==11) cnt++;
    cout<<cnt<<endl;
    return 0;
}

第3-2關 迴文數(中數據)

分析:由於L,R的範圍是10^7,能夠從L循環到R進行線性判斷每個數是否爲迴文數,判斷的方式爲將一個數的每一位進行分解,再從頭開始和從尾比較其對應位置是否數字相同。

標程:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int l,r,i,j,k,s,ans,high;
    int a[10];
    bool flag;
    cin>>l>>r;ans=0;
    for(i=l;i<=r;i++)
    {
        j=i;s=1e7;
        for(k=7;k>=0;k--)
        {
            a[k]=j/s;
            j%=s;s/=10;
        }
        for(high=7;high>=1;high--)
            if (a[high]) break;
        flag=true;
        for(j=0,k=high;j<k;j++,k--)
            if (a[j]!=a[k]) flag=false;
        if (flag) ans++;
    }
    cout<<ans<<endl;
    return 0;
}

第3-3關 迴文數(大數據)

分析:由於L,R的數據範圍爲10^13,因此直接for確定會超時。迴文的特色是,前一半和後一半是相等的。由樣例3可知,1到10^13的迴文數總數爲10999998。因此,咱們能夠考慮把1到10^13的全部迴文數所有枚舉出來,再判斷其是否在[L,R]區間內。枚舉迴文數的方法爲長度爲1位的數字枚舉到長度爲13位的數字,對於每種長度,首位和末尾能夠取1到9,中間各對稱位置能夠取0到9,用DFS的方式進行枚舉就好。

標程:

#include<bits/stdc++.h>
using namespace std;
long long l,r,ans,res;
long long ten[15];
int a[15];
void huiwen(int s,int k)
{
    int i;
    if (s==(k+1)/2)
    {
        res=0;
        for(i=0;i<k;i++)
            res+=a[i]*ten[i];
        if (res>=l && res<=r) ans++;
        return ;
    }
    if (s)
    {
        for(i=0;i<=9;i++)
        {
            a[s]=a[k-1-s]=i;
            huiwen(s+1,k);
        }
    }
    else
    {
        for(i=1;i<=9;i++)
        {
            a[s]=a[k-1-s]=i;
            huiwen(s+1,k);
        }
    }
}
int main()
{
    int i;
    cin>>l>>r;
    ten[0]=1;
    for(i=1;i<=13;i++)
        ten[i]=ten[i-1]*10;
    for(i=1;i<=13;i++)
        huiwen(0,i);
    cout<<ans<<endl;
    return 0;
}

第4-1關 睡覺(小數據)

分析:N的數據範圍只有1-4,而樣例已經告訴了你N爲1和N爲3時的答案,N爲2時很輕易能算出答案爲3*3=9,因此只需用四層for循環算出N=4的答案就好了。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,ans,a,b,c,d;
    cin>>n;ans=0;
    if (n==1) ans=3;
    if (n==3) ans=21;
    if (n==2) ans=3*3;
    if (n==4)
    {
        for(a=1;a<=3;a++)
            for(b=1;b<=3;b++)
                for(c=1;c<=3;c++)
                    for(d=1;d<=3;d++)
                     if (!((a!=b && b!=c && a!=c) || (b!=c && b!=d && c!=d))) ans++;
    }
    cout<<ans<<endl;
    return 0;
}

第4-2關 睡覺(中數據)

分析:N的數據範圍爲1-13,小卿卿天天可能跟三種不一樣的娃娃一塊兒睡覺,因此理論上最大有3^13=1594323種可能性。用DFS的方式就能夠統計出答案。

#include<bits/stdc++.h>
using namespace std;
int ans,n;
int a[15];
void dfs(int k)
{
    if (k==n+1)
    {
        ans++;return ;
    }
    for(int i=1;i<=3;i++)
    {
        a[k]=i;
        if (k>2 && a[k]!=a[k-1] && a[k]!=a[k-2] && a[k-1]!=a[k-2]) continue;
        dfs(k+1);
    }
}
int main()
{
    cin>>n;
    dfs(1);
    cout<<ans<<endl;
}

第4-3關 睡覺(大數據)

分析:N的數據範圍爲1-31,用第4-2關DFS的方法確定會超時,而這道題後面天天的睡覺方式跟前面的睡覺方式有聯繫。因此咱們能夠採用DP的方式解決這道問題。在某一天,小卿卿要選擇睡覺的娃娃時,若是以前兩天睡覺的娃娃相同,那麼她這一天能夠跟任一娃娃一塊兒睡覺,其最近三天最多隻跟兩種娃娃睡過覺;若是以前兩天睡覺的娃娃不一樣,那麼她這一天不能跟剩下那個以前兩天沒睡過覺的娃娃一塊兒睡覺。因此,咱們能夠設dp1[i]爲前i天最後兩天睡覺娃娃相同的方案數,dp2[i]爲前i天最後兩天睡覺娃娃不相同的方案數。dp1[i]+dp2[i]就是前i天的睡覺方案總數,其轉移方程爲dp1[i]=dp1[i-1]+dp2[i-1];dp2[i]=2*dp1[i-1]+dp2[i-1]。

標程:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    long long dp1[33],dp2[33];
    int i,n;
    dp1[1]=3;dp2[1]=0;
    cin>>n;
    for(i=2;i<=n;i++)
    {
        dp1[i]=dp1[i-1]+dp2[i-1];
        dp2[i]=2*dp1[i-1]+dp2[i-1];
    }
    cout<<dp1[n]+dp2[n]<<endl;
    return 0;
}
相關文章
相關標籤/搜索