标签:line min def 部分 class 统计 int dig span
建议改成:凯爹吊打 std
。
凯爹被卡常了,可恶啊。
基础篇,但成功暴露了基础很薄弱。T4 LCIS 完全没思路。
T1: 90 \(\rightarrow\) 80
对自己暴力太自信了,想数据点分治,但显然 \(O(10!\cdot 10)\) 显然是跑不过 500ms
的 = =。
其实也不好意思说是挂分,因为是乱搞的水了很多分。对拍大概每 3000,4000 组就挂了,但是数据太水,就很偷税
正解是和之前的哪一天她能重回我身边类似,但没有疾患鼠的情况所以更简单。同样两个值连边,统计联通块大小。
约瑟夫问题,但显然线性是过不去的。
打表发现(建议 \(m\) 取 \(4\),很容易找到规律),只有过了一段区间之后才会出现取模的情况,那就是目前的值比下标大的时候。那么我们显然可以计算出下次跳到需要取模的位置,中间直接乘法加上。
设下一次需要跳 \(x\) 步,目前的值是 \(a\),那么可以得到:
首先注意一定是小于,因为正好相等的时候是不能取模的,因为实际上正好相等的时候对应到 \(0\)~\(n-1\) 的编号是比下标小的。
简单移项改等号解得:
那么下次的下标就是 \(i+x\)。相等的时候需要特判一下,懂的都懂。
最后剩下的部分直接加上就好了。小于 \(m\) 的部分直接暴力。
时间复杂度 \(O(能过)\)。
当然前提是你要会线性解决约瑟夫问题的式子,可以看前几天的拿道题。
#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;
}
好像直接改改式子,就能用线段树区间加区间求和了。但是 T2 调了太久,所以本题 10 min 走人 = =。
LCIS 并输出方案,爷不会(wtcl)。
【考试反思】联赛模拟测试15 To be continued
标签:line min def 部分 class 统计 int dig span
原文地址:https://www.cnblogs.com/Midoria7/p/13807834.html