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分。
Code

#include<bits/stdc++.h>
using namespace std;
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;
        if(x<0)putchar('-'),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');
        return;
    }
}
using namespace io;
const int maxn=300,maxi=4510;
bool isl[maxn][maxn];
int te[maxn][maxn],dis[maxi][maxi],gpc,ans[maxi];
int lax[maxi],lay[maxi],len;
int dp[maxi][maxn<<1];
char s[maxn];
int n,m,xs,ys;
const int xx[4]={0,1,0,-1},yy[4]={1,0,-1,0};
inline bool ing(int x,int y)
{
    if(x>0&&x<=n&&y>0&&y<=m)return 1;
    return 0;
}
inline void dfs(int x,int y)
{
    te[x][y]=gpc;
    for(int i=0;i<4;i++)
    {
        int tox=x+xx[i],toy=y+yy[i];
        if(!ing(tox,toy))continue;
        if(!isl[tox][toy])continue;
        if(te[tox][toy])continue;
        dfs(tox,toy);
    }
    return;
}
struct node
{
    int di,id,ti;
};
queue<node>qu;
inline void bfs(int st,int lim,int tow)
{
    qu.push((node){0,st,1});ans[tow]=1;
    while(!qu.empty())
    {
        int x=qu.front().id,v=qu.front().di,t=qu.front().ti;
        qu.pop();
        if(v+dis[x][tow]<=lim)ans[tow]=max(ans[tow],t);
        for(int i=1;i<=gpc;i++)
        {
            if(i==x)continue;
            if(i==tow)continue;
            if(v+dis[i][x]>lim)continue;
            qu.push((node){v+dis[i][x],i,t+1});
        }
    }
    return;
}
int main()
{
    freopen("island.in","r",stdin);
    freopen("island.out","w",stdout);
    n=read();m=read();xs=read();ys=read();
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s+1);
        for(int j=1;j<=m;j++)isl[i][j]=s[j]-'0';
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(!isl[i][j])continue;
            lax[++len]=i;lay[len]=j;
            if(te[i][j])continue;
            gpc++;
            dfs(i,j);
        }
    }
    memset(dis,0x3f,sizeof(dis));
    for(int i=1;i<=len;i++)
    {
        dis[i][i]=0;
        for(int j=i+1;j<=len;j++)
        {
            if(te[lax[i]][lay[i]]==te[lax[j]][lay[j]])continue;
            dis[te[lax[i]][lay[i]]][te[lax[j]][lay[j]]]=min(dis[te[lax[i]][lay[i]]][te[lax[j]][lay[j]]],abs(lax[i]-lax[j])+abs(lay[i]-lay[j]));
            dis[te[lax[j]][lay[j]]][te[lax[i]][lay[i]]]=min(dis[te[lax[j]][lay[j]]][te[lax[i]][lay[i]]],abs(lax[i]-lax[j])+abs(lay[i]-lay[j]));
        }
    }
    memset(dp,-1,sizeof(dp));
    dp[te[xs][ys]][0]=0;
    for(int i=1;i<=n+m-2;i++)
    {
        for(int j=1;j<=gpc;j++)
        {
            for(int k=1;k<=gpc;k++)
            {
                if(j==k)continue;
                if(dis[j][k]>i)continue;
                if(dp[k][i-dis[j][k]]==-1)continue;
                dp[j][i]=max(dp[j][i],dp[k][i-dis[j][k]]+1);
            }
            if(dis[te[xs][ys]][j]>=i)
            {
                ans[j]=max(ans[j],dp[j][i]);
            }
        }
    }
    ans[te[xs][ys]]=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(!isl[i][j])putchar('0');
            else print(ans[te[i][j]]);
            putchar(' ');
        }putchar('\n');
    }
    return 0;
}

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;
}