1. 程式人生 > 其它 >11.1多校聯訓

11.1多校聯訓

T1 並王(bing)

Sol
卡常臭題。但是關我一個考場寫\(O(n^3)\)暴力什麼事呢?
好像可以優化到\(\sum_{i=1}^n f(n)\)\(f(n)\)表示\(n\)二進位制下1的個數。但是這是基於隨機資料優化。如果全部是\(2^{64}-1\)那效率甚至不如我的。
按位統計。從左往右:
如果第\(i\)個數二進位制第\(j\)位是1,那麼這一位貢獻就是\(\frac{(i-1)*(i-2)}{2}*(1<<j)\),表示前面隨便選兩個數都可以;同時\(t_j++\),表示目前有多少數第\(j\)位是1
如果第\(i\)個數二進位制第\(j\)位是0,那麼這一位貢獻就是\(f_j*(i-1-f_j)*(1<<j)\)

,表示前面選擇一個第\(j\)位是1,一個是0的,這樣異或起來就是1
綜上所述:開一個桶統計每一位當前1個數,時間複雜度\(O(64*n)\),且常數非常小(當然大於\(1\))。只帶O2只能1.09秒,火車頭加上輕鬆過。
Code

#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;
const int N=4000005;
int n, k;
int a[N], ans, U, seed;
int t[64];
signed main()
{
    freopen("bing.in", "r", stdin);
    freopen("bing.out", "w", stdout);
    scanf("%llu%llu%llu", &n, &seed, &k);
    U=(k==64?0ull:(1ull<<k))-1ull;
    mt19937_64 rnd(seed);
    for(int i=1; i<=n; ++i)
    {
        a[i]=rnd()&U;
        //do sth
        for(int j=63;~j;j--)
        {
            if((a[i]&(1ull<<j)))
            {
                ans+=(i-1ull)*(i-2ull)/2ull*(1ull<<j);
                t[j]++;
            }else ans+=t[j]*(i-1ull-t[j])*(1ull<<j);
        }
    }
    printf("%llu\n", ans);
    return 0;
}

T2、T3

都不會。不過T3的80分可以提一下。
對於80分,假設一共有\(k\)個島嶼\(x\)塊陸地,先\(O(n^2)\)DFS一遍算出每個點屬於的島嶼。然後\(O(x^2)\)計算一對島嶼之間的直飛距離。由於直飛距離顯然\(\leq n+m\),所以設\(dp[i][j]\)表示已經過長度為\(i\),現在在\(j\)最多坐了幾次飛機。那麼列舉每條邊即可,時間複雜度\(O(k^2n)\),雖然在最壞條件下\(subtask\ 3\;n\leq 90\)是過不了的,但是實際上資料比較水且本題1.5s開O2,所以能喜提80分。

T4 瑪雅歷(maya)

和julian異曲同工的臭題。
最大的統計天數也不超過long long資料範圍,所以先把輸入轉換成總計天數。然後把這個天數分段處理,我的做法分的比較細,先8月,然後-3114年,然後-3113-3101年,然後-3101

-2801年,然後-2801~-1年,然後公元年以後。
每次都更新一下當前時間,注意細節即可。票池的解法是先把400年的大迴圈暴力預處理出來,這裡時間複雜度\(O(10^5)\),很低。然後直接不斷取模再尋找對應日期就可以了,注意跨年的特殊處理即可。很可惜,最後突然改題幹以後票池炸了,或許慢慢來分類更穩吧。
Code(臭死了)

#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace io
{
    inline int read()
    {
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();}
        while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar();
        return f?x:-x;
    }
    inline void print(int x)
    {
        static int s[20],len;
        len=0;bool flag=0;
        if(x<0)flag=1,x=-x;
        if(x==0)
        {
            putchar('0');return;
        }
        while(x)
        {
            s[++len]=x%10;
            x/=10;
        }
        for(int i=len;i;i--)putchar(s[i]+'0');
        if(flag)putchar(' '),putchar('B'),putchar('C');
        return;
    }
}
int T,day;
const int month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
const int moth[13]={0,31,29,31,30,31,30,31,31,30,31,30,31};
int nd,nm,ny;
inline void output()
{
    using namespace io;
    print(day+1);putchar(' ');print(nm);putchar(' ');print(ny);putchar('\n');return;
}
inline void sibai()
{
    if(day<=36524)
    {
        ny+=4*(day/1461);
        day%=1461;
        if(day>=366)
        {
            day-=366;ny++;
            ny+=(day/365);
            day%=365;
            while(day>=month[nm])
            {
                day-=month[nm];nm++;
            }
            output();return;
        }else
        {
            while(day>=moth[nm])
            {
                day-=moth[nm];nm++;
            }
            output();return;
        }
    }
    day-=36525;ny+=100;
    ny+=100*(day/36524);
    day%=36524;
    if(day<=1459)
    {
        ny+=(day/365);
        day%=365;
        while(day>=month[nm])
        {
            day-=month[nm];nm++;
        }
        output();return;
    }
    day-=1460;ny+=4;
    ny+=4*(day/1461);
    day%=1461;
    if(day>=366)
    {
        day-=366;ny++;
        ny+=(day/365);
        day%=365;
        while(day>=month[nm])
        {
            day-=month[nm];nm++;
        }
        output();return;
    }else
    {
        while(day>=moth[nm])
        {
            day-=moth[nm];nm++;
        }
        output();return;
    }
}
signed main()
{
    freopen("maya.in","r",stdin);
    freopen("maya.out","w",stdout);
    using namespace io;
    T=read();
    while(T--)
    {
        day=0;nd=11,nm=8,ny=-3114;
        for(int i=1;i<=9;i++)day=day*(i==8?18:20)+read();
//        cout<<day<<endl;
        if(day<=20)
        {
            nd+=day;print(nd);putchar(' ');print(nm);putchar(' ');print(ny);putchar('\n');continue;
        }
        day-=21;nm=9;
        if(day<=121)
        {
            while(day>=month[nm])
            {
                day-=month[nm],nm++;
            }
            output();continue;
        }
        day-=122;nd=1;nm=1;ny=-3113;
        if(day<=4382)
        {
            ny+=4*(day/1461);
            day%=1461;
            if(day>=366)
            {
                day-=366;ny++;
                ny+=(day/365);
                day%=365;
                while(day>=month[nm])
                {
                    day-=month[nm];nm++;
                }
                output();continue;
            }else
            {
                while(day>=moth[nm])
                {
                    day-=moth[nm];nm++;
                }
                output();continue;
            }
        }
        day-=4383;nm=1;ny=-3101;
        if(day<=109571)
        {
            ny+=100*(day/36524);
            day%=36524;
            if(day<=1459)
            {
                ny+=(day/365);
                day%=365;
                while(day>=month[nm])
                {
                    day-=month[nm];nm++;
                }
                output();continue;
            }
            day-=1460;ny+=4;
            ny+=4*(day/1461);
            day%=1461;
            if(day>=366)
            {
                day-=366;ny++;
                ny+=(day/365);
                day%=365;
                while(day>=month[nm])
                {
                    day-=month[nm];nm++;
                }
                output();continue;
            }else
            {
                while(day>=moth[nm])
                {
                    day-=moth[nm];nm++;
                }
                output();continue;
            }
        }
        day-=109572;nm=1;ny=-2801;
        if(day<=1022678)
        {
            ny+=400*(day/146097);
            day%=146097;
            sibai();continue;
        }
        day-=1022679;
        if(day<=366)
        {
            nm=1;ny=-1;
            while(day>=moth[nm])
            {
                day-=moth[nm];nm++;
            }
            output();continue;
        }
        nm=1;ny=0;
        ny+=400*(day/146097);
        day%=146097;
        sibai();
    }
    return 0;
}