五校聯考解題報告


 

Day 1(題目在這兒)

 

T1 骰子

題意:

有一個 的網絡的左上角(1,1)有一個

有一個骰子上面為  1 ,下面為6 左面為 4,右面為 3,前面為 2,后面為 5),先從左滾

右然后滾下去滾到最左邊…..,每次記最上邊點數為每次得分,問滾完以后可以得多少分?

 

解:

開始定義shang=1,xia=6,zuo=4…

暴力:

對於 數據, 模擬在每個格子上的狀態,數據可以到10000左右不會超時。

而每次滾動需要考慮三種操作。

①     向左滾

右變上,上變左,左變下,下變右。

LL solz()
{
    LL temp=shang;
    shang=you;you=xia;xia=zuo;zuo=temp;
    return shang;
}

②     向右滾

LL soly()
{
    LL temp=shang;
    shang=zuo;zuo=xia;xia=you;you=temp;
    return shang;
}

③     向下滾

LL sold()
{
    LL temp=shang;
    shang=hou;hou=xia;xia=qian;qian=temp;
    return shang;
}

對於100%的數據,需要觀察一下篩子滾動的價值規律。

骰子對面相加價值為7,滾動一周價值為14,我們可以直接考慮滾動一行可以滾動多少周那么可以直接 14,然后一行剩余的最多枚舉3次,時間復雜度優秀。

/***************************
一輪noip模擬考試 Day1 T1
--2018.8.26
***************************/
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define LL long long
LL shang=1,xia=6,zuo=4,you=3,qian=2,hou=5;
LL n,m,sum,ans;
LL solz()
{
    LL temp=shang;
    shang=you;you=xia;xia=zuo;zuo=temp;
    return shang;
}
LL soly()
{
    LL temp=shang;
    shang=zuo;zuo=xia;xia=you;you=temp;
    return shang;
}
LL sold()
{
    LL temp=shang;
    shang=hou;hou=xia;xia=qian;qian=temp;
    return shang;
}
int main()
{
//    freopen("dice.in","r",stdin);
//    freopen("dice.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)
    {
        ans+=(m/4)*14;
        if(i%2==1&&m%4!=0)
        {
            ans+=shang;
            for(int j=1;j<m%4;j++)ans+=soly();            
        }
        else if(m%4!=0)
        {
            ans+=shang;
            for(int j=1;j<m%4;j++)ans+=solz();
        }
        sold();
    }
    printf("%lld",ans);
//    fclose(stdin);fclose(stdout);
}

 

T2 子序列

題意:

給定一個序列 .

求序列中有多少對三元組(I,j,k),滿足 或者$a[i] \le a[j] \le a[k]$或者$a[k] \le a[j] \le a[i]$ 。

 

解:

對於20%枚舉i,j,k即可。

對於50%, 處理某個數左邊有多少大於它的數,有多少小於它的數,右邊有多少…,然后枚舉j點,所以每個點滿足的三元組數量為

       左邊大於$a[j]$的個數$\times$右邊小的個數+左邊小的個數$\times$右邊大的個數

 

/*****************
考場50分代碼
********************/
int main()
{
    freopen("sub.in","r",stdin);
    freopen("sub.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            if(a[j]>a[i])big[i]++;
            if(a[j]<a[i])small[i]++;
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            if(a[j]!=a[i])
            {
                if(a[j]>a[i]&&big[j])ans+=big[j];
                if(a[j]<a[i]&&small[j])ans+=small[j];
                ans%=mod;
            }
        }
    }
    printf("%d",ans);
    fclose(stdin);fclose(stdout);
}

對於100%的數據,則需要先離散化,用到了兩個樹狀數組。

將復制離散化完的的數組排序,二分查找下標加到第一個樹狀數組里,區間[1,i]的和表示的為小於以i為下標的離散化數組中的數的個數,那么當枚舉到i時,樹狀數組中區間[1,a[i]-1](a[i]表示在離散化序列中a[i]的位置)的和表示a[1--i]中小於a[i]的數字個數,總數為i-1個,那么小於等於a[i]的數字個數為樹狀數組中區間[1,a[i]]的和,那么大於a[i]的數的個數為i-1-query(1,a[i-1])。

這部分代碼:

    for(int i=1;i<=n;i++)
    {
        a[i]=lower_bound(tmp+1,tmp+1+n,a[i])-tmp;
        l[i]=query(small,a[i]-1);    //比i小(左邊)
        ll[i]=i-1-query(small,a[i]);
        add(small,a[i],1);
    }

同理處理右邊的數,為了簡便可以倒序枚舉序列。

/************************
一輪Noip模擬賽Day 1 T2
--8.26
樹狀數組模板見於最后
*************************/
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define LL long long
#define mod int(1e9+7)
LL n,a[200010],big[200020],small[200010],ans;
LL tmp[200020];
LL l[200020],r[200020],ll[200020],rr[200020];
int lowbit(int i){ return i & -i; }
LL query(LL *c,LL i)
{
    LL sum=0;
    while(i>0)
    {
        sum+=c[i];
        i-=lowbit(i);
    }
    return sum;
}
LL add(LL *c,int i,LL val)
{
    while(i<=n)
    {
        c[i]+=val;
        i+=lowbit(i);
    }
}
int main()
{
//    freopen("sub.in","r",stdin);
//    freopen("sub.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        tmp[i]=a[i];
    }
    sort(tmp+1,tmp+1+n);
    for(int i=1;i<=n;i++)
    {
        a[i]=lower_bound(tmp+1,tmp+1+n,a[i])-tmp;
        l[i]=query(small,a[i]-1);    //比i小(左邊)
        ll[i]=i-1-query(small,a[i]);
        add(small,a[i],1);
    } 
    for(int i=n;i>=1;i--)
    {
        r[i]=query(big,a[i]-1);        //右邊比i小的。 
        rr[i]=n-i-query(big,a[i]);
        add(big,a[i],1);
    }
    for(int i=1;i<=n;i++)
    {
        ans+=(l[i]*rr[i])%mod;
        ans+=(ll[i]*r[i])%mod;
        ans%=mod;
    } 
    printf("%lld\n",ans);
//    fclose(stdin);fclose(stdout);
}

 

T3 平面圖

 

尚不會做正解,暫時只會10分。

子任務1:暴力搜索。

子任務3:n為奇數答案為0,偶數答案為2(開long long)

65遞推式:$$ans = ((pow((pow(n, 2) % HA - (3 * n - 3) % HA) % HA, m % HA) % HA + ((n - 1) % HA) * ( (pow(3 - n, m) % HA) + (pow((1 - n) % HA, m) % HA) ) % HA) % HA)  + (pow(n, 2) % HA) - (3 * n - 1) % HA;$$

HA為%數。

 

Day 2 (here)

T1

題意:

給你n個區間,每次區間[l,r]內的數+1,求最大的點數是多少?

 

解:

對於30%數據,O(n)枚舉區間每一個數每次+1,總復雜度O( )

對於另外20%, 離散化一下,枚舉+1.

另外20% 據說是考慮不會離散化的學生。

對於100%,標程居然比暴力都好寫。

離散化一下,每個區間的左端點處+1,r+1處-1,然后統計下前綴和,記錄最大的答案。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
#define LL long long
LL l[200010],r[200020],tmp[400010];
LL n,ans,MAX,k,sum[433330];

int main()
{
    freopen("meizi.in","r",stdin);
    freopen("meizi.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld%lld",&l[i],&r[i]);
        tmp[i*2-1]=l[i],tmp[i*2]=r[i];
    }
    sort(tmp+1,tmp+1+2*n);
    for(int i=1;i<=n;i++)
    {
        l[i]=lower_bound(tmp+1,tmp+1+2*n,l[i])-tmp;
        r[i]=lower_bound(tmp+1,tmp+1+2*n,r[i])-tmp;
        sum[l[i]]++;sum[r[i]+1]--;
    }
    for(int i=1;i<=2*n;i++)
    {
        sum[i]=sum[i-1]+sum[i];
        ans=max(ans,sum[i]);
    }
    printf("%lld",ans);
    fclose(stdin);fclose(stdout);
}

T2

 [無顯示]你網頁炸了!

T3

數學期望。

利用數學期望的線性性:期望的和等於和的期望。


免責聲明!

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



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