18.10.05模拟赛 总结 & T1 乖乖站好

先简单总结一下......

LYZ的题,还是挺好的。一点也不毒瘤。

还是有点考挂了......

第二题写了正解,然而并没有开long long......

T1水题我却没有看出来。

zwz大佬再次AK,太强了。

下面是T1 乖乖站好 standstill 的题解QAQ

这是一道神题。

思路极其......懂了正解之后感觉自己就是个xxx(手动和谐)。

然而我也只能说,这是道emmmm,好模拟。

题意:初始是1~n的序列。

每次变换如下:每k个为一组,组内第一个跑到最后一个的后面,最后不满k个的也视为一组。

即:若k=3,1 2 3 4 5会变成2 3 1 5 4

一共进行n-1次变换,k依次为2~n。

题解:暴力很好写,n方的。

每次变换的时候,一组的第一个要到最后一个的后面去,而这个位置也恰好被下一组的第一个让出来了(下一组的第一个也要往后走)。

这样对于组的大小为k的一次变换,只需要处理n/k个数。

最后的复杂度是n*(1/2+1/3+...+1/n)。

大概就是n*(H(n))(H(n)为调和级数部分和)

而根据某某数学定理,第n个调和数与n的自然对数的差值(即  )收敛于欧拉-马歇罗尼常数(这个常数约等于0.5772)。

所以总的复杂度就大概是n lg n。1e6的数据可在0.2s左右跑完(还是不加输出优化的)。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 int n;
 7 int a[2000005];
 8 
 9 void print(int x)
10 {
11     if(x/10)print(x/10);
12     putchar(x%10+'0');
13 }
14 
15 int main()
16 {
17     freopen("standstill.in","r",stdin);
18     freopen("standstill.out","w",stdout);
19     scanf("%d",&n);
20     for(int i=1;i<=n;i++)a[i]=i;
21     for(int i=2;i<=n;i++)
22     {
23         int bef=n+i-1,p=(n-1)/i*i+i-1;
24         while(p>0)
25         {
26             a[bef]=a[p];
27             bef=p;
28             p-=i;
29         }
30     }
31     for(int i=n;i<2*n;i++)print(a[i]),putchar(32);
32     fclose(stdin);
33     fclose(stdout);
34     return 0;
35 }

猜你喜欢

转载自www.cnblogs.com/eternhope/p/9745877.html