codechef November Challenge 2017解题报告

第二次被ceilks艹翻的无奈啊。。

Villages and Tribes

模拟不解释

#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
#define N 100009
using namespace std;
char a[N];
int main()
{
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while (T--)
    {
        cin>>a;
        int last=-1,pos=-1,ans1=0,ans2=0,n=strlen(a);
        for (int i=0;i<n;i++)
        {
            if (a[i]=='A'&&last==0)
            {
                ans1+=i-pos-1;
                pos=i;
            }
            if (a[i]=='B'&&last==1)
            {
                ans2+=i-pos-1;
                pos=i;
            }
            if (a[i]=='A')
            {
                ans1++;
                last=0;
                pos=i;
            }
            if (a[i]=='B')
            {
                ans2++;
                last=1;
                pos=i;
            }
        }
        cout<<ans1<<" "<<ans2<<endl;
    }
    return 0;
}

Chef goes Left Right Left

判断对区间就好。

#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
#define inf 2e9
using namespace std;
int main()
{
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while (T--)
    {
        int n,x;
        cin>>n>>x;
        int last=0,flag=1,now,Min=-inf,Max=inf;
        for (int i=1;i<=n;i++)
        {
            cin>>now;
            if (i>1&&now>last&&last>x|now<last&&last<x) flag=0;
            if (now>=Max||now<=Min) flag=0;
            if (now>x) Max=min(Max,now);
            if (now<x) Min=max(Min,now);
            last=now;
        }
        if (now!=x) flag=0;
        cout<<(flag?"YES":"NO")<<endl;
    }
    return 0;
}

Periodic Palindrome Construction

除了特判就没了。

#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
using namespace std;
int main()
{
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while (T--)
    {
        int x,y;
        cin>>x>>y;
        if (y<=2) cout<<"impossible"<<endl;
        else
        {
            if (y&1)
            {
                for (int t=1;t<=x/y;t++)
                    for (int i=1;i<=y;i++) cout<<(i&1?"a":"b");
            }
            else
            {
                for (int t=1;t<=x/y;t++)
                {
                    for (int i=1;i<=y/2;i++) cout<<(i&1?"a":"b");
                    for (int i=y/2+1;i<=y;i++) cout<<(i&1?"b":"a");
                }
            }
            cout<<endl;
        }
    }
    return 0;
}

Chef Hates Palindromes

字符集大小 A3 的,显然形如 abcabc 的串是没有长度大于2的回文子串的,然后等于2的发现小范围打表暴力,大范围都可以表示为 abaabb 的循环串。

#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
using namespace std;
const char a[6]={'a','b','a','a','b','b'};
const char b[3]={'a','b','c'};
int main()
{
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while (T--)
    {
        int n,A;
        cin>>n>>A;
        if (A==1)
        {
            cout<<n<<" ";
            for (int i=1;i<=n;i++) cout<<'a';
            cout<<endl;
        }
        if (A==2)
        {
            if (n==1) cout<<"1 a\n";
            else if (n==2) cout<<"1 ab\n";
            else if (n==3) cout<<"2 aab\n";
            else if (n==4) cout<<"2 aabb\n";
            else if (n==5) cout<<"3 aaaba\n";
            else if (n==6) cout<<"3 aaabab\n";
            else if (n==7) cout<<"3 aaababb\n";
            else if (n==8) cout<<"3 aaababbb\n";
            else
            {
                cout<<"4 ";
                for (int i=0;i<n;i++) cout<<a[i%6];
                cout<<endl;
            }
        }
        if (A>=3)
        {
            cout<<"1 ";
            for (int i=0;i<n;i++) cout<<b[i%3];
            cout<<endl;
        }
    }
    return 0;
}

Chef and Subarray Queries

无脑线段树维护就好了。

#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
#define root 1,1,n
#define mid (l+r>>1)
#define lc cur<<1
#define rc lc|1
#define lson lc,l,mid
#define rson rc,mid+1,r
#define N 500009
using namespace std;
int n,q,L,R;
struct node
{
    ll ans1,ans2;
    int l_len1,r_len1,l_len2,r_len2,Max;
    void change(int x)
    {
        Max=x;
        if (x<L) l_len1=r_len1=ans1=1;
        else l_len1=r_len1=ans1=0;
        if (x<=R) l_len2=r_len2=ans2=1;
        else l_len2=r_len2=ans2=0;
    }
    friend node operator +(const node &lhs,const node &rhs)
    {
        node ret;
        ret.Max=max(lhs.Max,rhs.Max);
        if (lhs.Max<L) ret.l_len1=lhs.l_len1+rhs.l_len1;
        else ret.l_len1=lhs.l_len1;
        if (rhs.Max<L) ret.r_len1=rhs.r_len1+lhs.r_len1;
        else ret.r_len1=rhs.r_len1;
        if (lhs.Max<=R) ret.l_len2=lhs.l_len2+rhs.l_len2;
        else ret.l_len2=lhs.l_len2;
        if (rhs.Max<=R) ret.r_len2=rhs.r_len2+lhs.r_len2;
        else ret.r_len2=rhs.r_len2;
        ret.ans1=(ll)lhs.r_len1*rhs.l_len1+lhs.ans1+rhs.ans1;
        ret.ans2=(ll)lhs.r_len2*rhs.l_len2+lhs.ans2+rhs.ans2;
        return ret;
    }
}tr[N<<2];
void build(int cur,int l,int r)
{
    if (l==r)
    {
        tr[cur].change(0);
        return;
    }
    build(lson);
    build(rson);
    tr[cur]=tr[lc]+tr[rc];
}
void change(int cur,int l,int r,int x,int y)
{
    if (l==r)
    {
        tr[cur].change(y);
        return;
    }
    if (x<=mid) change(lson,x,y);
    else change(rson,x,y);
    tr[cur]=tr[lc]+tr[rc];
}
node qry(int cur,int l,int r,int L,int R)
{
    if (L<=l&&R>=r) return tr[cur];
    if (R<=mid) return qry(lson,L,R);
    else
        if (L>mid) return qry(rson,L,R);
        else return qry(lson,L,R)+qry(rson,L,R);
}
int main()
{
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>n>>q>>L>>R;
    build(root);
    while (q--)
    {
        int op,x,y;
        cin>>op>>x>>y;
        if (op==1) change(root,x,y);
        else
        {
            node Ans=qry(root,x,y);
            printf("%lld\n",Ans.ans2-Ans.ans1);
        }
    }
    return 0;
}

Product on the segment by modulo

似乎是个套路?
原来以为只是CRT然后卡卡常数,后来发现似乎我过不了(不知道又没有过的啊)。
发现有除法就得计算逆元或者类似的东西,很烦,考虑只有乘法。
如果可以离线,显然可以分治轻松过,然而这题强制在线,所以我们将分治每一层 [l,r] 区间中到 mid=l+r2 的前缀后缀积算出来,显然就可以在询问时小常数 O(logn) 查询出所在区间并计算了。(似乎是uoj上某位大佬写的)

#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
#define pii pair<int,int>
#define mid (l+r>>1)
#define N 2000009
using namespace std;
int n,m,mod,q,last,x,y,L,R,a[N],b[N][21];
void solve(int l,int r,int k)
{
    if (l==r)
    {
        b[l][k]=a[l]%mod;
        return;
    }
    for (int i=mid;i>=l;i--)
        b[i][k]=(i==mid?(a[i]%mod):((ll)b[i+1][k]*a[i]%mod));
    for (int i=mid+1;i<=r;i++)
        b[i][k]=(i==mid+1?(a[i]%mod):((ll)b[i-1][k]*a[i]%mod));
    solve(l,mid,k+1);
    solve(mid+1,r,k+1);
}
int get(int l,int r)
{
    if (l==r) return a[l]%mod;
    for (int i=m>>1,j=0;;i>>=1,j++)
        if (!(l&i)&&(r&i))
        {
            //cout<<i<<endl;
            return (ll)b[l][j]*b[r][j]%mod;
        }
}
int main()
{
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while (T--)
    {
        cin>>n>>mod>>q;
        for (int i=0;i<n;i++) cin>>a[i];
        m=1;
        while (m<n) m<<=1;
        solve(0,m-1,0);
        L=R=last=0;
        cin>>y;
        for (int i=0;i<q;i++)
        {
            if (i%64==0)
            {
                x=y;
                cin>>y;
                L=(x+last)%n;
                R=(y+last)%n;
            }
            else
            {
                L=(L+last)%n;
                R=(R+last)%n;
            }
            if (L>R) swap(L,R);
            last=(get(L,R)+1)%mod;
            //cout<<L<<R<<last-1<<endl;
        }
        cout<<last<<endl;
    }
    return 0;
}

Lovers Gift

正着做似乎挺难,考虑倒着做。
相当于原来有一堆有银行的城市,逐渐减少到零。
我们发现相当于求跟这个点不在同一个连通块中的点的第二大点权值。
每次少一个银行相当于将一堆连通块合并(假装把每个银行当成特殊的一种连通块)。每个连通块维护前两大权值,然后塞入set中,每次合并连通块,删去set中少掉的两个值。每次在set中最多查询4个就必然可以查询到。
总复杂度大概 O((n+m)(logn+α(n)))

#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
#define N 100009
using namespace std;
int n,m,first[N],number,vis[N],fa[N],pd[N],Max[N][2];
struct edge
{
    int to,next;
    void add(int x,int y)
    {
        to=y,next=first[x],first[x]=number;
    }
}e[N<<1];
set<int,greater<int> > st;
set<int,greater<int> > ::iterator it;
struct mdy
{
    int op,x,Ans;
}q[N];
int read()
{
    int x=1;
    char ch;
    while (ch=gc,ch<'0'||ch>'9') if (ch=='-') x=-1;
    int s=ch-'0';
    while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-'0';
    return s*x;
}
void dfs(int x,int y)
{
    fa[x]=y;
    if (x>Max[y][0]) Max[y][1]=Max[y][0],Max[y][0]=x;
    else if (x>Max[y][1]) Max[y][1]=x;
    vis[x]=1;
    for (int i=first[x];i;i=e[i].next)
        if (!vis[e[i].to]&&!pd[e[i].to]) dfs(e[i].to,y);
}
int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
    x=find(x),y=find(y);
    if (Max[x][0]>Max[y][0])
    {
        fa[y]=x;
        if (Max[x][1]>Max[y][0])
        {
            st.erase(Max[y][0]);
            st.erase(Max[y][1]);
        }
        else
        {
            st.erase(Max[x][1]);
            st.erase(Max[y][1]);
            Max[x][1]=Max[y][0];
        }
    }
    else
    {
        fa[x]=y;
        if (Max[y][1]>Max[x][0])
        {
            st.erase(Max[x][0]);
            st.erase(Max[x][1]);
        }
        else
        {
            st.erase(Max[x][1]);
            st.erase(Max[y][1]);
            Max[y][1]=Max[x][0];
        }
    }
}
int main()
{
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    int T;
    cin>>T;
    while (T--)
    {
        cin>>n>>m;
        for (int i=1;i<=n;i++) pd[i]=vis[i]=first[i]=0,fa[i]=i;
        number=0;
        for (int i=1;i<n;i++)
        {
            int x,y;
            cin>>x>>y;
            e[++number].add(x,y),e[++number].add(y,x);
        }
        for (int i=1;i<=m;i++)
        {
            cin>>q[i].op>>q[i].x;
            if (q[i].op==1) pd[q[i].x]++;
        }
        memset(Max,0,sizeof(Max));
        for (int i=1;i<=n;i++)
            if (!vis[i]&&!pd[i]) dfs(i,i);
            else if (pd[i]) Max[i][0]=i;
        st.clear();
        for (int i=1;i<=n;i++)
            if (find(i)==i)
            {
                if (Max[i][0]) st.insert(Max[i][0]);
                if (Max[i][1]) st.insert(Max[i][1]);
            }
        for (int i=m;i;i--)
        {
            if (q[i].op==1)
            {
                if (--pd[q[i].x]) continue;
                for (int j=first[q[i].x];j;j=e[j].next)
                    if (!pd[e[j].to]) merge(q[i].x,e[j].to);
            }
            else
            {
                int flag=1;
                it=st.begin();
                for (int j=1;j<=2;j++)
                {
                    while (it!=st.end()&&(find((*it))==find(q[i].x)&&(!pd[*it]))) it++;
                    if (it==st.end())
                    {
                        flag=0;
                        break;
                    }
                    if (j==1) it++;
                }
                if (flag) q[i].Ans=*it;
                else q[i].Ans=-1;
            }
        }
        for (int i=1;i<=m;i++)
            if (q[i].op==2) cout<<q[i].Ans<<endl;
    }
    return 0;
}

Polynomials

这题我调试出来我自己都不信了啊。
相当于求 n 个(小于)三次函数的类似半平面交的东西。
考虑将n个函数归并处理,据外校大佬说似乎可以证明最终区间数小于等于 O(n) 个。(大概最多3倍?)
然后就是考虑两个三次函数求交点了。
这次比赛的结果告诉我们,中国人发明的公式虽然看起来很菜,但实际上是最好用的(盛金公式)(雾)。

#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
#define mid (l+r>>1)
#define N 100003
#define inf 2e5
#define eps 1e-9
using namespace std;
ll n,q,Ans[N];
struct jiao
{
    double x,y,z;
    jiao(double x=0.0,double y=0.0,double z=0.0):x(x),y(y),z(z){}
};
struct func
{
    ll a0,a1,a2,a3;
    double f(double x)
    {
        return (double)a0+a1*x+a2*x*x+a3*x*x*x;
    }
}a[N];
struct node
{
    ll beg,pos;
    node(ll beg=0,ll pos=0):beg(beg),pos(pos){}
};
struct line
{
    vector <node> q;
};
jiao get_jiao(ll pos1,ll pos2)
{
    if (a[pos1].a3==a[pos2].a3)
    {
        if (a[pos1].a2==a[pos2].a2)
        {
            if (a[pos1].a1==a[pos2].a1) return jiao(inf+1,inf+1,inf+1);
            return jiao((double)(a[pos2].a0-a[pos1].a0)/(a[pos1].a1-a[pos2].a1),inf+1,inf+1);
        }
        else
        {
            ll A=a[pos1].a2-a[pos2].a2;
            ll B=a[pos1].a1-a[pos2].a1;
            ll C=a[pos1].a0-a[pos2].a0;
            double delta=B*B-4.0*A*C;
            if (fabs(delta)<eps) return jiao(-B/2.0/(double)A,inf+1,inf+1);
            if (delta<0) return jiao(inf+1,inf+1,inf+1);
            return jiao((-B-sqrt(delta))/2.0/A,(-B+sqrt(delta))/2.0/A,inf+1);
        }
    }
    else
    {
        ll aa=a[pos1].a3-a[pos2].a3;
        ll bb=a[pos1].a2-a[pos2].a2;
        ll cc=a[pos1].a1-a[pos2].a1;
        ll dd=a[pos1].a0-a[pos2].a0;
        double A=bb*bb-3*aa*cc;
        double B=bb*cc-9*aa*dd;
        double C=cc*cc-3*bb*dd;
        if (fabs(A)<eps&&fabs(B)<eps) return jiao(-B/3.0/(double)A,inf+1,inf+1);
        double delta=B*B-4*A*C;
        if (fabs(delta)<eps) return jiao(-bb/aa+B/A,-B/2.0/A,inf+1);
        if (delta>0)
        {
            double Y1=A*bb+3.0*aa*(-B+sqrt(delta))/2.0;
            double Y2=A*bb+3.0*aa*(-B-sqrt(delta))/2.0;
            if (Y1>0) Y1=pow(Y1,1.0/3.0);
            else Y1=-pow(fabs(Y1),1.0/3.0);
            if (Y2>0) Y2=pow(Y2,1.0/3.0);
            else Y2=-pow(fabs(Y2),1.0/3.0);
            double X1=(-bb-Y1-Y2)/3.0/aa;
            return jiao(X1,inf+1,inf+1);
        }
        double T=(2.0*A*bb-3.0*aa*B)/(2.0*pow(A,1.5));
        double th=acos(T);
        double X1=(-bb-2.0*sqrt(A)*cos(th/3.0))/3.0/aa;
        double X2=(-bb+sqrt(A)*(cos(th/3.0)+sqrt(3.0)*sin(th/3.0)))/3.0/aa;
        double X3=(-bb+sqrt(A)*(cos(th/3.0)-sqrt(3.0)*sin(th/3.0)))/3.0/aa;
        return jiao(X1,X2,X3);
    }
}
line solve(ll l,ll r)
{
    if (l==r)
    {
        line ret;
        ret.q.clear();
        ret.q.push_back(node(0,l));
        return ret;
    }
    line ret;
    ret.q.clear();
    line L=solve(l,mid);
    line R=solve(mid+1,r);
    ll now=0,now_pos=0;
    for (ll i=0;i<(ll)L.q.size();)
    {
        if (now_pos>((i==(ll)L.q.size()-1)?inf:L.q[i+1].beg-1)) i++;
        if (i==(ll)L.q.size()) break;
        ll rpos1=(i==(ll)L.q.size()-1)?inf:L.q[i+1].beg-1;
        while (((now<(R.q.size()-1))?(R.q[now+1].beg-1):(inf))<now_pos) now++;
        ll lpos2=R.q[now].beg,rpos2=(now==(ll)R.q.size()-1)?inf:(R.q[now+1].beg-1);
        ll lpos=now_pos,rpos=min(rpos1,rpos2);
        //if (l==1&&r==5) cout<<now_pos<<" "<<lpos2<<" "<<rpos2<<endl;
        jiao ji=get_jiao(L.q[i].pos,R.q[now].pos);
        vector<double> Q;
        if (ji.x<inf&&ji.x>=lpos&&ji.x<=rpos) Q.push_back(ji.x);
        if (ji.y<inf&&ji.y>=lpos&&ji.y<=rpos) Q.push_back(ji.y);
        if (ji.z<inf&&ji.z>=lpos&&ji.z<=rpos) Q.push_back(ji.z);
        Q.push_back(lpos),Q.push_back(rpos);
        sort(Q.begin(),Q.end());
        for (ll j=1;j<Q.size();j++)
        {
            ll pos=Q[j-1];
            if (pos<Q[j-1]) pos++;
            if (a[L.q[i].pos].f(pos)<a[R.q[now].pos].f(pos))
                ret.q.push_back(node(pos,L.q[i].pos));
            else
                if (a[L.q[i].pos].f(pos)>a[R.q[now].pos].f(pos))
                    ret.q.push_back(node(pos,R.q[now].pos));
                else
                    if (a[L.q[i].pos].f(pos+0.5)<a[R.q[now].pos].f(pos+0.5))
                        ret.q.push_back(node(pos,L.q[i].pos));
                    else
                        ret.q.push_back(node(pos,R.q[now].pos));
            if (ret.q.size()>=2)
                if (ret.q.back().pos==(ret.q[ret.q.size()-2].pos)) ret.q.pop_back();
        }
        now_pos=rpos+1;
    }
    return ret;
}
int main()
{
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    ll T;
    cin>>T;
    while (T--)
    {
        cin>>n;
        for (ll i=1;i<=n;i++)
            cin>>a[i].a0>>a[i].a1>>a[i].a2>>a[i].a3;
        line ret=solve(1,n);
        //puts("-----------------------");
        cin>>q;
        ll now=0;
        for (ll i=0;i<N;i++)
        {
            while (now<(ret.q.size()-1)&&ret.q[now+1].beg<=i) now++;
            Ans[i]=ret.q[now].pos;
        }
        while (q--)
        {
            ll x;
            cin>>x;
            cout<<(ll)a[Ans[x]].f(x)<<endl;
        }
    }
    return 0;
}

Day Schedule

我只想知道为什么缩写跟题目名字毫无关系??(BINOMSUM)
据梁大大刚开赛时说,dls这道题只会40分。(合理猜测:dls:这TM40分不是随便拿;某大佬:woc??!!dls只会40!!好难!!)然后一天后,梁大大又跟我说他会了。(woc,梁大大果然无敌了啊)
这题调试出来那可能我更不信了。。
好吧来理一理思路。
首先我们发现这题的A(娱乐活动数??)和K(天数)是给定的。
所以对于每一天,不同的D,它的方案数我们可以表示成一个多项式。
先忽略第一个小时的特点,我们发现活动可以分为两种:即进行娱乐或者进行娱乐后吃饭。
根据这个我们可以很轻松地写出这个多项式:

f(D)=i=0n2CiniDiAni,(n=k1)

通过这个公式我们发现我们似乎一分都拿不到(wtf??)
所以前面的公式屁用没有。。。
(下文高能预警)
考虑将这个多项式 f(D) 表示为上升幂形式。
也就是说:
f(D)=i=0n2aij=1i(D+j)

然后带入答案式子:
Ans=T=0Tmax1CLD+Tf(D+T)=T=0Tmax1(D+T)!L!(D+TL)!i=0n2aij=1i(D+T+j)=T=0Tmax1(D+T)!L!(D+TL)!i=0n2ai(D+T+i)!(D+T)!=T=0Tmax11L!i=0n2ai(D+T+i)!(D+TL)!=T=0Tmax11L!i=0n2aiCL+iD+T+i(L+i)!=i=0n2ai(L+i)!L!T=0Tmax1CL+iD+T+i=i=0n2ai(L+i)!L!(CL+i+1D+Tmax+iCL+i+1D+i)

通过预处理阶乘和阶乘逆元,我们可以做到 O(K) 的时间回答每一次询问,所以我们只需要考虑 ai 系数数组如何求得。
m=n2
考虑
f(D)=i=0maij=1i(D+j)

D=1,2,,m1
发现
f(1)=a0

f(2)=a0a1

f(m1)=i=0mbi(1)im!(mi)!=m!i=0mbi(1)i(mi)!

考虑构造多项式
F(x)=i=0mf(i1)i!xi

我们发现 F=A×B
其中
A(x)=i=0maixi

B(x)=i=0m(x)ii!

而F的系数可以通过矩阵快速幂求得,于是a就可以在b这个多项式求逆后得到。(然而由于模数输入,我就写了(拉的模板)3个NTT质数NTT后CRT得到答案)
然而还可以更优秀(wanglichao1121发现的),我们发现 B(x) 的逆元显然就是
B(x)=i=0mxii!
(可以考虑 ex 的泰勒展开)
至此,这道题就完美完成了。。
(中间的乘法实际上可以分治乘并不需要NTT然而我分治乘的常数实在太大了)

#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
#define N 200009
#define M 12000009
using namespace std;
ll a[M],inv[M],f[N],b[N],inv_b[N],p[N];
ll n,k,A,mod,q,m;
ll L,D,T;
struct matrix
{
    ll a[2][2];
    friend matrix operator *(const matrix &A,const matrix &B)
    {
        matrix ret;
        for (int i=0;i<2;i++)
            for (int j=0;j<2;j++)
            {
                ret.a[i][j]=0;
                for (int k=0;k<2;k++) ret.a[i][j]=(ret.a[i][j]+A.a[i][k]*B.a[k][j]%mod)%mod;
            }
        return ret;
    }
};
#define K 3
const ll mm[K]={1004535809,998244353,104857601};
#define G 3
ll qpow(ll x,ll k,ll P)
{
    ll ret=1;
    while (k)
    {
        if (k&1) ret=1LL*ret*x%P;
        k>>=1;
        x=1LL*x*x%P;
    }
    return ret;
}
struct _NTT
{
    ll w[2][N],P;
    void init(ll _P)
    {
        P=_P;
    }
    void pre(ll n)
    {
        w[0][0]=w[0][n]=w[1][0]=w[1][n]=1;
        ll GG=qpow(G,(P-1)/n,P);
        for (ll i=1;i<n;i++) w[0][i]=w[0][i-1]*GG%P;
        for (ll i=1;i<n;i++) w[1][i]=w[0][n-i];
    }
    void change(ll *y,ll len)
    {
        for (ll i=1,j=len/2;i<len-1;++i)
        {
            if (i<j) swap(y[i],y[j]);
            ll k=len/2;
            while (j>=k)
            {
                j-=k;
                k/=2;
            }
            j+=k;
        }
    }
    void NTT(ll *a,ll n,ll v)
    {
        for (ll i=0,j=0;i<n;i++)
        {
            if (i>j) swap(a[i],a[j]);
            for (ll l=n>>1;(j^=l)<l;l>>=1);
        }
        for (ll i=2;i<=n;i<<=1)
            for (ll j=0;j<n;j+=i)
                for (ll l=0;l<i>>1;l++)
                {
                    ll t=a[j+l+(i>>1)]*w[v][(n/i)*l]%P;
                    a[j+l+(i>>1)]=(a[j+l]-t+P)%P;
                    a[j+l]=(a[j+l]+t)%P;
                }
        if (v)
            for (ll i=0,t=qpow(n,P-2,P);i<n;i++) a[i]=a[i]*t%P;
    }
    void mul(ll A[],ll B[],ll len)
    {
        pre(len);
        NTT(A,len,0);
        NTT(B,len,0);
        for (ll i=0;i<len;++i) A[i]=1LL*A[i]*B[i]%P;
        NTT(A,len,1);
    }
}ntt[K];
ll tmp[N][K],t1[N],t2[N];
ll r[K][K];
ll CRT(ll a[])
{
    ll x[K];
    for (ll i=0;i<K;++i)
    {
        x[i]=a[i];
        for (ll j=0;j<i;++j)
        {
            ll t=(x[i]-x[j])%mm[i];
            if (t<0) t+=mm[i];
            x[i]=1LL*t*r[j][i]%mm[i];
        }
    }
    ll mul=1,ret=x[0]%mod;
    for (ll i=1;i<K;++i)
    {
        mul=1LL*mul*mm[i-1]%mod;
        ret+=1LL*x[i]*mul%mod;
        if (ret>=mod) ret-=mod;
    }
    return ret;
}
void mul(ll A[],ll B[],ll len,ll C[])
{
    for (ll id=0;id<K;++id)
    {
        for (ll i=0;i<len;++i)
        {
            t1[i]=A[i];
            t2[i]=B[i];
        }
        ntt[id].mul(t1,t2,len);
        for (ll i=0;i<len;++i)
            tmp[i][id]=t1[i];
    }
    for (ll i=0;i<len;++i)
        C[i]=CRT(tmp[i]);
}
void init()
{
    for (ll i=0;i<K;++i)
        for (ll j=0;j<i;++j)
            r[j][i]=qpow(mm[j],mm[i]-2,mm[i]);
    for (ll i=0;i<K;++i)
        ntt[i].init(mm[i]);
}
ll ksm(ll x,ll y)
{
    ll ret=1;
    for (;y;y>>=1,x=x*x%mod)
        if (y&1) ret=ret*x%mod;
    return ret;
}
ll miao[N],lych[N],aa[N],bb[N],cc[N],dd[N],ee[N],ff[N],gg[N];
/*void mul(ll a[],ll b[],ll m,ll c[])
{
    if (m==1)
    {
        c[0]=(ll)a[0]*b[0]%mod;
        return;
    }
    for (int i=0;i<m;i++)
    {
        if (i<(m>>1)) bb[i]=a[i],dd[i]=b[i];
        else aa[i-(m>>1)]=a[i],cc[i-(m>>1)]=b[i];
    }
    mul(aa,cc,m>>1,ee);
    mul(bb,dd,m>>1,ff);
    for (int i=0;i<(m>>1);i++)
        aa[i]=(aa[i]+bb[i])%mod,cc[i]=(cc[i]+dd[i])%mod;
    mul(aa,cc,m>>1,gg);
    for (int i=0;i<(m<<1);i++) c[i]=0;
    for (int i=0;i<m;i++)
        c[i+m]=(c[i+m]+ee[i])%mod;
    for (int i=0;i<m;i++)
        c[i+(m>>1)]=(c[i+(m>>1)]+gg[i]-ee[i]-ff[i]+mod+mod)%mod;
    for (int i=0;i<m;i++)
        c[i]=(c[i]+ff[i])%mod;
}*/
ll c(ll n,ll m)
{
    if (n<m) return 0;
    return (ll)a[n]*inv[m]%mod*inv[n-m]%mod;
}
ll get_f(ll x)
{
    matrix zy,ret;
    ret.a[1][0]=ret.a[1][1]=ret.a[0][0]=0,ret.a[0][1]=1;
    zy.a[0][0]=zy.a[1][0]=A;
    zy.a[0][1]=x,zy.a[1][1]=0;
    for (ll i=n;i;i>>=1,zy=zy*zy)
        if (i&1) ret=ret*zy;
    return (ret.a[0][0]+ret.a[0][1])%mod;
}
void get_inv(ll a[],ll b[],ll m)
{
    if (m==1)
    {
        b[0]=ksm(a[0],mod-2);
        return;
    }
    get_inv(a,miao,m>>1);
    for (int i=(m>>1);i<m;i++) miao[i]=0;
    for (int i=0;i<m;i++) aa[i]=a[i];
    for (int i=m;i<(m<<1);i++) aa[i]=0;
    mul(aa,miao,m<<1,lych);
    lych[0]=(mod+2-lych[0])%mod;
    for (int i=1;i<m;i++) lych[i]=mod-lych[i];
    for (int i=m;i<(m<<1);i++) lych[i]=0;
    mul(miao,lych,m<<1,b);
    for (int i=m;i<(m<<1);i++) b[i]=0;
}
int main()
{
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    init();
    cin>>k>>A>>mod>>q;
    n=k-1;
    m=1;
    while (m<=n/2) m<<=1;
    a[0]=1;
    for (ll i=1;i<M;i++) a[i]=a[i-1]*i%mod;
    inv[0]=inv[1]=1;
    for (ll i=2;i<M;i++) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    for (ll i=2;i<M;i++) inv[i]=inv[i]*inv[i-1]%mod;
    for (ll i=0;i<m;i++)
        f[i]=get_f(mod-i-1)*inv[i]%mod;
    for (ll i=0;i<m;i++)
        b[i]=inv[i];
    get_inv(b,inv_b,m);
    ll wlc[N];
    memset(wlc,0,sizeof(wlc));
    mul(inv_b,b,m<<1,wlc);
    mul(f,inv_b,m<<1,p);
    for (int i=0;i<=n/2;i++)
        if (i&1) p[i]=mod-p[i];
    while (q--)
    {
        cin>>L>>D>>T;
        ll Ans=0;
        for (ll i=0;i<=n/2;i++)
        {
            ll ret=p[i]*a[i+L]%mod*inv[L]%mod;
            ret=ret*(c(D+i+T,i+L+1)-c(D+i,i+L+1)+mod)%mod;
            Ans=(Ans+ret)%mod;
        }
        Ans=(Ans%mod+mod)%mod;
        cout<<Ans<<endl;
    }
    return 0;
}

Chef and Intersection Line

这道题第一个难点在于判断线段相交,这个是计算几何的问题,然而可以全部存为int判断。
然后先来考虑一种比较直接的想法。
每一时刻都尽量选择最优(权值最大)的点加入答案,这样只需要写一个线段相交就可以。我们发现这样的得分大概在55分左右(一开始有60分好像)。
然后根据我们的答案可以画出(写个程序吧孩子)大致路线图。发现它在没有什么限制的条件时,选择的点往往太过于远了。(简单来说,太浪了)
所以我们将当前点排序时要加入离上一个点的曼哈顿距离作为第二个参数。这样大概调一下参数,再枚举起点,大概可以在中间的某一个时刻获得100分。(后来91、2分这样子)
这样似乎还是不够优秀,因为它往往还是太浪了。。
所以(以下为梁大大想出)我们思考枚举中间点的位置(比如说第25个点实在哪),然后向两边宽搜。这样似乎又多了点分。。
似乎剩下加的优化就只有对于第二种数据生成方式,按照固定的路线跑了。(似乎又多了一点分)
最后这样大概就94分了。(梁大大似乎参数比我强很多啊,日本小哥和ceilks可能还有高论啊,我果然还是最菜啊)

#include <bits/stdc++.h>
#define gc getchar()
#define ll long long
#define M 509
#define N 59
#define zero(x) ((x)==0)
#define inf 1e9
using namespace std;
int n,m,a[M][N][N],pd[N][N],Max,ID,Time,type;
const double alpha[4]={0.4,2.0,0.95,1.0};
const int MAX_SIZE[2][2]={{-1,100},{50,50}};
int MID;
struct point
{
    int x,y;
    point(int x=0,int y=0):x(x),y(y){}
    friend point operator +(const point &A,const point &B)
    {
        return point(A.x+B.x,A.y+B.y);
    }
    friend point operator -(const point &A,const point &B)
    {
        return point(A.x-B.x,A.y-B.y);
    }
    friend point operator *(const point &A,const int &B)
    {
        return point(A.x*B,A.y*B);
    }
};
int xmult(point p1,point p2,point p0)
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
int dmult(point p1,point p2,point p0)
{
    return (p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);
}
int dots_inline(point p1,point p2,point p3)
{
    return zero(xmult(p1,p2,p3));
}
int dot_online_in(point p,point l1,point l2)
{
    return zero(xmult(p,l1,l2))&&(l1.x-p.x)*(l2.x-p.x)<=0&&(l1.y-p.y)*(l2.y-p.y)<=0;
}
int same_side(point p1,point p2,point l1,point l2)
{
    return xmult(l1,p1,l2)*xmult(l1,p2,l2)>0;
}
int parallel(point u1,point u2,point v1,point v2)
{
    return zero((u1.x-u2.x)*(v1.y-v2.y)-(v1.x-v2.x)*(u1.y-u2.y));
}
int intersect_in(point u1,point u2,point v1,point v2)
{
    int x=xmult(u1,v2,v1)*xmult(u2,v2,v1);
    int y=xmult(v1,u2,u1)*xmult(v2,u2,u1);
    if (x>0||y>0) return 0;
    if (x<0&&y<0) return 1;
    return dot_online_in(u1,v1,v2)||dot_online_in(u2,v1,v2)||dot_online_in(v1,u1,u2)||dot_online_in(v2,u1,u2);
}
struct node
{
    int x,y,z,val;
    node(int x=0,int y=0,int z=0,int val=0):x(x),y(y),z(z),val(val){}
    bool operator <(const node &rhs) const
    {
        return val>rhs.val||(val==rhs.val&&(x<<6|y)<(rhs.x<<6|rhs.y));
    }
};
vector<point> Ans,Final;
double get(node x)
{
    return x.val-(double)alpha[ID]*(4.0-Time/125.0)*(abs(x.x-Ans.back().x)+abs(x.y-Ans.back().y));
}
bool cmp(node x,node y)
{
    return get(x)>get(y);
}
double Get(node x)
{
    return x.val-(double)alpha[ID]*(abs(x.x-Ans.back().x)+abs(x.y-Ans.back().y));
}
bool Cmp(node x,node y)
{
    return Get(x)>Get(y);
}
double get1(node x)
{
    return x.val-(double)alpha[ID+2]*(abs(x.x-Ans[Time-1].x)+abs(x.y-Ans[Time-1].y));
}
bool cmp1(node x,node y)
{
    return get1(x)>get1(y);
}
vector<node> p[M];
bool check(int x,int y)
{
    if (pd[x][y]) return 0;
    if ((int)Ans.size()<=1) return 1;
    int ed=Ans.size()-1;
    if (dots_inline(Ans[ed-1],Ans[ed],point(x,y)))
        if (!(Ans[ed].x<Ans[ed-1].x&&x<Ans[ed].x||x>Ans[ed].x&&Ans[ed].x>Ans[ed-1].x)&&!(Ans[ed].y<Ans[ed-1].y&&y<Ans[ed].y||y>Ans[ed].y&&Ans[ed].y>Ans[ed-1].y)) return 0;
    for (int i=1;i<ed;i++)
        if (intersect_in(Ans[i-1],Ans[i],Ans[ed],point(x,y))) return 0;
    return 1;
}
bool check_inv(int x,int y)
{
    if (pd[x][y]) return 0;
    if ((int)Ans.size()<=1) return 1;
    int beg=0;
    if (dots_inline(Ans[beg+1],Ans[beg],point(x,y)))
        if (!(Ans[beg].x<Ans[beg+1].x&&x<Ans[beg].x||x>Ans[beg].x&&Ans[beg].x>Ans[beg+1].x)&&!(Ans[beg].y<Ans[beg+1].y&&y<Ans[beg].y||y>Ans[beg].y&&Ans[beg].y>Ans[beg+1].y)) return 0;
    for (int i=beg+2;i<(int)Ans.size();i++)
        if (intersect_in(Ans[i-1],Ans[i],Ans[beg],point(x,y))) return 0;
    return 1;
}
bool is_ok(int x,int y)
{
    if (pd[x][y]) return 0;
    if (x>n||x<1||y>n||y<1) return 0;
    return 1;
}
node q[M];
int bfs(int k,int x,int y)
{
    int head=1,tail=1,ret=a[k][x][y];
    q[tail]=node(x,y,k,a[k][x][y]);
    bool flag=0;
    while (head<=tail)
    {
        if (head==1)
        {
            int t_now=k-1;
            Time=k;
            node cho=node(0,0,0,-inf);
            int num=0;
            for (int i=0;i<(int)p[t_now].size();i++)
            {
                node now=p[t_now][i];
                if (check_inv(now.x,now.y))
                {
                    if (cmp1(now,cho)) cho=now;
                    if ((++num)>3) break;
                }
            }
            if (num)
            {
                ret+=cho.val;
                Ans.insert(Ans.begin(),point(cho.x,cho.y));
                pd[cho.x][cho.y]=1;
                q[++tail]=cho;
            }
            t_now=k+1;
            cho=node(0,0,0,-inf);
            num=0;
            for (int i=0;i<(int)p[t_now].size();i++)
            {
                node now=p[t_now][i];
                if (check(now.x,now.y))
                {
                    if (cmp1(now,cho)) cho=now;
                    if ((++num)>3) break;
                }
            }
            if (num)
            {
                ret+=cho.val;
                Ans.push_back(point(cho.x,cho.y));
                pd[cho.x][cho.y]=1;
                q[++tail]=cho;
            }
        }
        else
        {
            int t_now=(q[head].z<k)?q[head].z-1:q[head].z+1;
            if (t_now==0)
            {
                flag=1;
                head++;
                continue;
            }
            if (t_now>m)
            {
                head++;
                continue;
            }
            Time=k;
            node cho=node(0,0,0,-inf);
            int num=0;
            for (int i=0;i<(int)p[t_now].size();i++)
            {
                node now=p[t_now][i];
                if ((t_now>k)?check(now.x,now.y):check_inv(now.x,now.y))
                {
                    if (cmp1(now,cho)) cho=now;
                    if ((++num)>3) break;
                }
            }
            if (num)
            {
                ret+=cho.val;
                if (t_now<k) Ans.insert(Ans.begin(),point(cho.x,cho.y));
                else Ans.push_back(point(cho.x,cho.y));
                pd[cho.x][cho.y]=1;
                q[++tail]=cho;
            }
        }
        head++;
    }
    if (!flag) return 0;
    return ret;
}
int main()
{
    int ttt=clock();
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>n>>m;
    if (m==50) ID=0;
    else ID=1;
    for (int i=1;i<=m;i++)
    {
        p[i].clear();
        for (int j=1;j<=n;j++)
            for (int k=1;k<=n;k++)
            {
                cin>>a[i][j][k];
                p[i].push_back(node(j,k,i,a[i][j][k]));
            }
    }
    int sss=0;
    sss+=a[1][1][1]+a[1][1][2]+a[1][2][1];
    sss+=a[1][1][n]+a[1][1][n-1]+a[1][2][n];
    sss+=a[1][n][1]+a[1][n-1][1]+a[1][n][2];
    sss+=a[1][n][n]+a[1][n-1][n]+a[1][n][n-1];
    if (sss>=500) type=1;
    else type=0;
    int ret=0;
    for (int i=1;i<=m;i++) sort(p[i].begin(),p[i].end());
    if (m==50&&type==0)
        for (int t=0;t<n*n;t++)
        {
            memset(pd,0,sizeof(pd));
            Ans.clear();
            Ans.push_back(point(p[1][t].x,p[1][t].y));
            ret=p[1][t].val;
            pd[p[1][t].x][p[1][t].y]=1;
            for (int i=2;i<=m;i++)
            {
                bool flag=0;
                for (int j=0;j<(int)p[i].size();j++)
                {
                    node now=p[i][j];
                    if (check(now.x,now.y))
                    {
                        flag=1;
                        ret+=now.val;
                        Ans.push_back(point(now.x,now.y));
                        pd[now.x][now.y]=1;
                        break;
                    }
                }
                if (!flag) break;
            }
            if (ret>Max)
            {
                Max=ret;
                Final.clear();
                for (int i=0;i<(int)Ans.size();i++)
                    Final.push_back(Ans[i]);
            }
        }
    if (m==50&&type==0) cerr<<Max<<endl;
    for (int t=0;t<MAX_SIZE[ID][type];t++)
    {
        memset(pd,0,sizeof(pd));
        Ans.clear();
        Ans.push_back(point(p[1][t].x,p[1][t].y));
        pd[p[1][t].x][p[1][t].y]=1;
        ret=p[1][t].val;
        for (int i=1;i<2500;i++) assert(p[1][i-1].val>=p[1][i].val);
        for (int i=2;i<=m;i++)
        {
            Time=i;
            sort(p[i].begin(),p[i].end(),Cmp);
            bool flag=0;
            for (int j=0;j<(int)p[i].size();j++)
            {
                node now=p[i][j];
                if (check(now.x,now.y))
                {
                    flag=1;
                    ret+=now.val;
                    Ans.push_back(point(now.x,now.y));
                    pd[now.x][now.y]=1;
                    break;
                }
            }
            if (!flag) break;
        }
        if (ret>Max)
        {
            Max=ret;
            Final.clear();
            for (int i=0;i<(int)Ans.size();i++)
                Final.push_back(Ans[i]);
        }
    }
    if (m!=50||type==1) cerr<<Max<<endl;
    for (int i=1;i<=m;i++) sort(p[i].begin(),p[i].end());
    if (m==50&&type==0)
    {
        for (MID=22;MID<=28;MID++)
            for (int t=0;t<n*n;t++)
                if (p[MID][t].val>3)
                {
                    int i=p[MID][t].x,j=p[MID][t].y;
                    memset(pd,0,sizeof(pd));
                    Ans.clear();
                    Ans.push_back(point(i,j));
                    pd[i][j]=1;
                    ret=bfs(MID,i,j);
                    if (ret>Max)
                    {
                        Max=ret;
                        Final.clear();
                        for (int k=0;k<(int)Ans.size();k++)
                            Final.push_back(Ans[k]);
                    }
                }
        cerr<<Max<<endl;
    }
    if (m==500)
    {
        for (MID=44;MID<=56;MID++)
            for (int t=0;t<n*n;t++)
                if (p[MID][t].val>35)
                {
                    int i=p[MID][t].x,j=p[MID][t].y;
                    memset(pd,0,sizeof(pd));
                    Ans.clear();
                    Ans.push_back(point(i,j));
                    pd[i][j]=1;
                    ret=bfs(MID,i,j);
                    if (ret>Max)
                    {
                        Max=ret;
                        Final.clear();
                        for (int k=0;k<(int)Ans.size();k++)
                            Final.push_back(Ans[k]);
                    }
                }
        cerr<<Max<<endl;
    }
    if (m==500&&type==1)
    {
        Ans.clear();
        ret=Time=0;
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,10-i+1)),ret+=a[++Time][j][10-i+1];
        }
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,i+40)),ret+=a[++Time][j][i+40];
        }
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-(i-j),40+i)),ret+=a[++Time][50-(i-j)][40+i];
        }
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-j+1,11-i)),ret+=a[++Time][50-j+1][11-i];
        }
        for (int i=40;i>=16;i--)
            Ans.push_back(point(i,1)),ret+=a[++Time][i][1];
        for (int i=16;i<=25;i++)
            for (int j=41-i;j<=i+10;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        for (int i=26;i<=35;i++)
            for (int j=i-10;j<=61-i;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        if (ret>Max)
        {
            Max=ret;
            Final.clear();
            for (int k=0;k<(int)Ans.size();k++)
                Final.push_back(Ans[k]);
        }
        cerr<<Max<<endl;
    }
    if (m==500&&type==1)
    {
        for (int i=1;i<=m;i++)
            for (int j=1;j<=n;j++)
                for (int k=1;k*2<=n;k++)
                    swap(a[i][j][k],a[i][j][n-k+1]);
        Ans.clear();
        ret=Time=0;
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,10-i+1)),ret+=a[++Time][j][10-i+1];
        }
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,i+40)),ret+=a[++Time][j][i+40];
        }
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-(i-j),40+i)),ret+=a[++Time][50-(i-j)][40+i];
        }
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-j+1,11-i)),ret+=a[++Time][50-j+1][11-i];
        }
        for (int i=40;i>=16;i--)
            Ans.push_back(point(i,1)),ret+=a[++Time][i][1];
        for (int i=16;i<=25;i++)
            for (int j=41-i;j<=i+10;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        for (int i=26;i<=35;i++)
            for (int j=i-10;j<=61-i;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        if (ret>Max)
        {
            Max=ret;
            Final.clear();
            for (int k=0;k<(int)Ans.size();k++)
                Final.push_back(point(Ans[k].x,n-Ans[k].y+1));
        }
        cerr<<Max<<endl;
        for (int i=1;i<=m;i++)
            for (int j=1;j<=n;j++)
                for (int k=1;k*2<=n;k++)
                    swap(a[i][j][k],a[i][j][n-k+1]);
    }
    if (m==500&&type==1)
    {
        for (int i=1;i<=m;i++)
            for (int j=1;j*2<=n;j++)
                for (int k=1;k<=n;k++)
                    swap(a[i][j][k],a[i][n-j+1][k]);
        Ans.clear();
        ret=Time=0;
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,10-i+1)),ret+=a[++Time][j][10-i+1];
        }
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,i+40)),ret+=a[++Time][j][i+40];
        }
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-(i-j),40+i)),ret+=a[++Time][50-(i-j)][40+i];
        }
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-j+1,11-i)),ret+=a[++Time][50-j+1][11-i];
        }
        for (int i=40;i>=16;i--)
            Ans.push_back(point(i,1)),ret+=a[++Time][i][1];
        for (int i=16;i<=25;i++)
            for (int j=41-i;j<=i+10;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        for (int i=26;i<=35;i++)
            for (int j=i-10;j<=61-i;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        if (ret>Max)
        {
            Max=ret;
            Final.clear();
            for (int k=0;k<(int)Ans.size();k++)
                Final.push_back(point(n-Ans[k].x+1,Ans[k].y));
        }
        cerr<<Max<<endl;
        for (int i=1;i<=m;i++)
            for (int j=1;j*2<=n;j++)
                for (int k=1;k<=n;k++)
                    swap(a[i][j][k],a[i][n-j+1][k]);
    }
    if (m==500&&type==1)
    {
        for (int i=1;i<=m;i++)
            for (int j=1;j*2<=n;j++)
                for (int k=1;k<=n;k++)
                    swap(a[i][j][k],a[i][n-j+1][k]);
        for (int i=1;i<=m;i++)
            for (int j=1;j<=n;j++)
                for (int k=1;k*2<=n;k++)
                    swap(a[i][j][k],a[i][j][n-k+1]);
        Ans.clear();
        ret=Time=0;
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,10-i+1)),ret+=a[++Time][j][10-i+1];
        }
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,i+40)),ret+=a[++Time][j][i+40];
        }
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-(i-j),40+i)),ret+=a[++Time][50-(i-j)][40+i];
        }
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-j+1,11-i)),ret+=a[++Time][50-j+1][11-i];
        }
        for (int i=40;i>=16;i--)
            Ans.push_back(point(i,1)),ret+=a[++Time][i][1];
        for (int i=16;i<=25;i++)
            for (int j=41-i;j<=i+10;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        for (int i=26;i<=35;i++)
            for (int j=i-10;j<=61-i;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        if (ret>Max)
        {
            Max=ret;
            Final.clear();
            for (int k=0;k<(int)Ans.size();k++)
                Final.push_back(point(n-Ans[k].x+1,n-Ans[k].y+1));
        }
        cerr<<Max<<endl;
        for (int i=1;i<=m;i++)
            for (int j=1;j*2<=n;j++)
                for (int k=1;k<=n;k++)
                    swap(a[i][j][k],a[i][n-j+1][k]);
        for (int i=1;i<=m;i++)
            for (int j=1;j<=n;j++)
                for (int k=1;k*2<=n;k++)
                    swap(a[i][j][k],a[i][j][n-k+1]);
    }
    if (m==500&&type==1)
    {
        Ans.clear();
        ret=Time=0;
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,10-i+1)),ret+=a[++Time][j][10-i+1];
        }
        for (int i=11;i<=40;i++) Ans.push_back(point(1,i)),ret+=a[++Time][1][i];
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,i+40)),ret+=a[++Time][j][i+40];
        }
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-(i-j),40+i)),ret+=a[++Time][50-(i-j)][40+i];
        }
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-j+1,11-i)),ret+=a[++Time][50-j+1][11-i];
        }
        for (int i=40;i>=16;i--)
            Ans.push_back(point(i,1)),ret+=a[++Time][i][1];
        for (int i=16;i<=25;i++)
            for (int j=41-i;j<=i+10;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        for (int i=26;i<=35;i++)
            for (int j=i-10;j<=61-i;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        if (ret>Max)
        {
            Max=ret;
            Final.clear();
            for (int k=0;k<(int)Ans.size();k++)
                Final.push_back(Ans[k]);
        }
        cerr<<Max<<endl;
    }
    if (m==500&&type==1)
    {
        for (int i=1;i<=m;i++)
            for (int j=1;j<=n;j++)
                for (int k=1;k*2<=n;k++)
                    swap(a[i][j][k],a[i][j][n-k+1]);
        Ans.clear();
        ret=Time=0;
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,10-i+1)),ret+=a[++Time][j][10-i+1];
        }
        for (int i=11;i<=40;i++) Ans.push_back(point(1,i)),ret+=a[++Time][1][i];
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,i+40)),ret+=a[++Time][j][i+40];
        }
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-(i-j),40+i)),ret+=a[++Time][50-(i-j)][40+i];
        }
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-j+1,11-i)),ret+=a[++Time][50-j+1][11-i];
        }
        for (int i=40;i>=16;i--)
            Ans.push_back(point(i,1)),ret+=a[++Time][i][1];
        for (int i=16;i<=25;i++)
            for (int j=41-i;j<=i+10;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        for (int i=26;i<=35;i++)
            for (int j=i-10;j<=61-i;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        if (ret>Max)
        {
            Max=ret;
            Final.clear();
            for (int k=0;k<(int)Ans.size();k++)
                Final.push_back(point(Ans[k].x,n-Ans[k].y+1));
        }
        cerr<<Max<<endl;
        for (int i=1;i<=m;i++)
            for (int j=1;j<=n;j++)
                for (int k=1;k*2<=n;k++)
                    swap(a[i][j][k],a[i][j][n-k+1]);
    }
    if (m==500&&type==1)
    {
        for (int i=1;i<=m;i++)
            for (int j=1;j*2<=n;j++)
                for (int k=1;k<=n;k++)
                    swap(a[i][j][k],a[i][n-j+1][k]);
        Ans.clear();
        ret=Time=0;
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,10-i+1)),ret+=a[++Time][j][10-i+1];
        }
        for (int i=11;i<=40;i++) Ans.push_back(point(1,i)),ret+=a[++Time][1][i];
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,i+40)),ret+=a[++Time][j][i+40];
        }
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-(i-j),40+i)),ret+=a[++Time][50-(i-j)][40+i];
        }
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-j+1,11-i)),ret+=a[++Time][50-j+1][11-i];
        }
        for (int i=40;i>=16;i--)
            Ans.push_back(point(i,1)),ret+=a[++Time][i][1];
        for (int i=16;i<=25;i++)
            for (int j=41-i;j<=i+10;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        for (int i=26;i<=35;i++)
            for (int j=i-10;j<=61-i;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        if (ret>Max)
        {
            Max=ret;
            Final.clear();
            for (int k=0;k<(int)Ans.size();k++)
                Final.push_back(point(n-Ans[k].x+1,Ans[k].y));
        }
        cerr<<Max<<endl;
        for (int i=1;i<=m;i++)
            for (int j=1;j*2<=n;j++)
                for (int k=1;k<=n;k++)
                    swap(a[i][j][k],a[i][n-j+1][k]);
    }
    if (m==500&&type==1)
    {
        for (int i=1;i<=m;i++)
            for (int j=1;j*2<=n;j++)
                for (int k=1;k<=n;k++)
                    swap(a[i][j][k],a[i][n-j+1][k]);
        for (int i=1;i<=m;i++)
            for (int j=1;j<=n;j++)
                for (int k=1;k*2<=n;k++)
                    swap(a[i][j][k],a[i][j][n-k+1]);
        Ans.clear();
        ret=Time=0;
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,10-i+1)),ret+=a[++Time][j][10-i+1];
        }
        for (int i=11;i<=40;i++) Ans.push_back(point(1,i)),ret+=a[++Time][1][i];
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(j,i+40)),ret+=a[++Time][j][i+40];
        }
        for (int i=10;i;i--)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-(i-j),40+i)),ret+=a[++Time][50-(i-j)][40+i];
        }
        for (int i=1;i<=10;i++)
        {
            for (int j=1;j<=i;j++)
                Ans.push_back(point(50-j+1,11-i)),ret+=a[++Time][50-j+1][11-i];
        }
        for (int i=40;i>=16;i--)
            Ans.push_back(point(i,1)),ret+=a[++Time][i][1];
        for (int i=16;i<=25;i++)
            for (int j=41-i;j<=i+10;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        for (int i=26;i<=35;i++)
            for (int j=i-10;j<=61-i;j++)
                Ans.push_back(point(i,j)),ret+=a[++Time][i][j];
        if (ret>Max)
        {
            Max=ret;
            Final.clear();
            for (int k=0;k<(int)Ans.size();k++)
                Final.push_back(point(n-Ans[k].x+1,n-Ans[k].y+1));
        }
        cerr<<Max<<endl;
        for (int i=1;i<=m;i++)
            for (int j=1;j*2<=n;j++)
                for (int k=1;k<=n;k++)
                    swap(a[i][j][k],a[i][n-j+1][k]);
        for (int i=1;i<=m;i++)
            for (int j=1;j<=n;j++)
                for (int k=1;k*2<=n;k++)
                    swap(a[i][j][k],a[i][j][n-k+1]);
    }
    for (int i=0;i<(int)Final.size();i++)
        cout<<Final[i].x<<" "<<Final[i].y<<endl;
    if ((int)Final.size()<m) cout<<-1<<" "<<-1<<endl;
    cerr<<clock()-ttt<<endl;
    return 0;
}

附图:
第一种数据
第二种数据
可怕的文件数量

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值