其他分享
首页 > 其他分享> > 【考试反思】联赛模拟测试15 To be continued

【考试反思】联赛模拟测试15 To be continued

作者:互联网

建议改成:凯爹吊打 std

凯爹被卡常了,可恶啊。

基础篇,但成功暴露了基础很薄弱。T4 LCIS 完全没思路。

T1: 90 \(\rightarrow\) 80

T1:游戏

对自己暴力太自信了,想数据点分治,但显然 \(O(10!\cdot 10)\) 显然是跑不过 500ms的 = =。

其实也不好意思说是挂分,因为是乱搞的水了很多分。对拍大概每 3000,4000 组就挂了,但是数据太水,就很偷税

正解是和之前的哪一天她能重回我身边类似,但没有疾患鼠的情况所以更简单。同样两个值连边,统计联通块大小。

T2:嘟嘟噜

约瑟夫问题,但显然线性是过不去的。

打表发现(建议 \(m\) 取 \(4\),很容易找到规律),只有过了一段区间之后才会出现取模的情况,那就是目前的值比下标大的时候。那么我们显然可以计算出下次跳到需要取模的位置。

设下一次需要跳 \(x\) 步,目前的值是 \(a\),那么可以得到:

\[i+x<a+m\times x \]

首先注意一定是小于,因为正好相等的时候是不能取模的,因为实际上正好相等的时候对应到 \(0\)~\(n-1\) 的编号是比下标小的。

简单移项改等号解得:

\[x=\bigg\lceil \cfrac{i-a}{m-1} \bigg\rceil \]

那么下次的下标就是 \(i+x\)。相等的时候需要特判一下,懂的都懂。

最后剩下的部分直接加上就好了。小于 \(m\) 的部分直接暴力。

时间复杂度 \(O(能过)\)。

当然前提是你要会线性解决约瑟夫问题的式子,可以看前几天的拿道题。

Code
#include <bits/stdc++.h>
using namespace std;

inline int read(){
    int x=0;bool fopt=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar())if(ch=='-')fopt=0;
    for(;isdigit(ch);ch=getchar())x=(x<<3)+(x<<1)+ch-48;
    return fopt?x:-x;
}

int main(){
#ifndef LOCAL
    freopen("mayuri.in","r",stdin);
    freopen("mayuri.out","w",stdout);
#endif
    int T=read();
    while(T--){
        int n=read(),m=read(),x=0,i=m;
        for(register int j=2;j<=min(n,m);j++){
            x=(x+m)%j;
        }
        if(n<=m)printf("%d\n",x+1);
        else{
            x+=1;//记得+1!
            while(1){
                int nxt=i+(int)ceil(1.0*(i-x)/(m-1));
                if(nxt>n)break;
                x=(x+(nxt-i)*m);
                if(x==nxt){
                    if(++nxt>n)break;
                    x=(x+m)%nxt;
                }else x%=nxt;
                i=nxt;
            }
            x+=(n-i)*m;
            printf("%d\n",x);
        }
    }
    return 0;
}

T3:天才绅士少女助手克里斯蒂娜

好像直接改改式子,就能用线段树区间加区间求和了。但是 T2 调了太久,所以本题 10 min 走人= =。

T4:凤凰院凶真

LCIS 并输出方案,爷不会(wtcl)。

标签:取模,ch,15,联赛,nxt,10,下标,continued,getchar
来源: https://www.cnblogs.com/Midoria7/p/13807834.html