专栏文章

题解:P11506 [ROIR 2017 Day 1] 校园

P11506题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@miql2fyw
此快照首次捕获于
2025/12/04 06:33
3 个月前
此快照最后确认于
2025/12/04 06:33
3 个月前
查看原文

题意

一个表格有 nn 行,无限多列,在每一列中要求行数为 kk 的倍数的格子里有 xx 个数,其他各自中有 yy 个数,格子中的数按照自然数顺序排序。共 qq 次询问,求给出的数 a1,a2,,aqa_1, a_2, \dots, a_q 在表格中的行数。
下图是一种 n=7n = 7, k=3k = 3, x=2x = 2, y=3y = 3 的情况,同题面样例:

思路

如果对于每一次询问,直接按照题意模拟填数的话,时间复杂度为 O(qn)\text{O} (qn) ,显然只能通过 subtask #1 。
考虑优化,规定每填 k1k - 1yy11xx 为一个周期。
我们可以预处理出每一列填入数字的数量一个完整周期内填入数字的数量 STS_TSkS_k ,如果 ai>STa_i > S_T , 那么 aia_i 所在的行数与 ai=aimodST{a_i}^{\prime} = a_i \bmod S_T (ai<ST{a_i}^{\prime} < S_T) 所在的行数相同,可以缩小一定范围的常数。
接下来对于每次询问 ai{a_i}^{\prime} ,我们可以计算出其经历了几个完整的周期,以及周期之外最后剩余的行数。这些都可以通过数学方法直接处理,时间复杂度 O(q)\text{O} (q)
  • 在周期之内,计算经历了几个完整的周期,直接用 ai{a_i}^{\prime} 整除 SkS_k 即可。这一部分答案为周期数乘以周期 kk
  • 在周期以外,因为每个周期前 k1k-1 格均为 yy 情况,最后 11 格为 xx 情况,我们先判断其是否在周期的最后 11 行,如果是,这一部分答案即为周期 kk 。反之则前面每一格内数量均为 yy ,使用周期外数字的数量除以 yy ,判断一下是否整除即可。
以样例为例, ST=8S_T = 8Sk=19S_k = 19 ,若询问 a1=50a_1 = 50 ,那么 a1=a1modn=12{a_1}^{\prime} = a_1 \bmod n = 12a1{a_1}^{\prime} 经历了 11 个完整的周期,最终剩余 22 行,所以最终答案为 3+2=53 + 2 = 5
核心判断语句如下:
CPP
ll query(ll a){
    if(a==0) return n;
    ll block=a/Sk,tmp=block*Sk;// block 代表经历了几个完整周期, tmp 代表前面的周期有多少个数
    //printf("%lld block:%lld tmp:%lld\n",a,block,tmp);
    a-=tmp;
    if(a<=(k-1)*y){//全 y
        if(a%y) return block*k+a/y+1;
        else return block*k+a/y;
    }else{//含有 x & y
        return block*k+k;
    }
}

代码

闲话

很好的签到题,注意 ai1018a_i \leq 10^{18} 要开 long long 。

评论

1 条评论,欢迎与作者交流。

正在加载评论...