zoukankan      html  css  js  c++  java
  • Jzoj5421 嘟嘟噜

    由于众所周知的原因, 冈部一直欠真由理一串香蕉.
    为了封上真由理的嘴, 冈部承诺只要真由理回答出这个问题, 就给她买一车的香蕉:
    一开始有n 个人围成一个圈, 从1 开始顺时针报数, 报出m 的人被机关处决. 然后下一个人再从1 开始报数, 直到只剩下一个人.
    红莉栖: “这不就是约瑟夫问题吗...”
    伦太郎: “助手你给我闭嘴!”
    真由理虽然已经晕头转向了, 但听到有一车的香蕉, 两眼便放出了光芒.

    约瑟夫问题:10^9版,m<=10^5

    我们知道有一个O(n)的算法:s=(s+m)%i {i=1~n}

    然而这样只能70分,我们需要改进算法

    我们发现当i大于m的时候,其实有些步骤是可以合并为一步的,这个和反演里面用的那个除法很像

    那我们根据当前i-s%i可以得出,接下来(i-s%i)/m步是可以合为一步走的,在接下来这些过程中,取模不会改变s+m的值

    让后就可以乱搞,复杂度O(玄学)≈O(√n)

    #pragma GCC optimize("O3")
    #pragma G++ optimize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    int n,m,s=0,T;
    int main(){
    	freopen("mayuri.in","r",stdin);
    	freopen("mayuri.out","w",stdout);
    	for(scanf("%d",&T);T--;){
    		s=0;
    		scanf("%d%d",&n,&m);
    //		for(int i=2;i<=n;++i) s=(s+m)%i;
    		for(int i=2,p;i<=n;){
    			p=(i-s-1)/m+1;
    			if(i+p>n) p=n-i+1;
    			s=(s+m*p)%(i+p-1);
    			i=i+p;
    		}
    		printf("%d
    ",++s);
    	}
    }

  • 相关阅读:
    hdu-1698(线段树,区间修改)
    hdu-1394(线段树)
    hdu-1166(线段树)
    hdu-1251(string+map)
    hdu-1711(kmp算法)
    hdu-2191(完全背包+二进制优化模板)
    hdu-2844(完全背包+二进制优化模板)
    hdu-1171(多重背包+二进制优化)
    SpringMVC 参数中接收数组、List写法
    如何高效的查询数组中是否包含某个值
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477225.html
Copyright © 2011-2022 走看看