zoukankan      html  css  js  c++  java
  • 【题解】「THUPC 2019」令人难以忘记的题目名称

    题目链接

    一个人选串,另一个人旋转。

    容易发现,如果原串(S)有长度为(len)的循环节,若Alice选的串(T)的循环节长度也为(len),则不管Bob怎么转,(S')的循环节长度最大为(len)。如果(len=1),那么就可以在一步之内完成。

    然后就可以开始乱搞找规律了。

    (len=4,P=2),发现可以;取(len=2,P=3),发现不行;取(len=6,P=2),发现也不行。

    由此得(cāi)出结论:当(len=P^k)时可以胜利,反之不行。

    然后来观(xiā)察(gǎo)一下(|S|=len=P=5)的情况,发现当(S=[0,1,2,3,4])的时候,取(T=[4,3,2,1,0]),就可以把(len)变为(1)。继续尝试,会发现(S=[0,2,4,1,3])的时候,给它加个([3,1,4,2,0])也行

    观察这两个序列有什么共同点,可以发现它们的差分序列(d;(d_i=S_i-S_{i-1},d_1=S_1-S_{len}))的循环节长度为(1)

    推广一下,如果(S)(t)阶差分序列的循环节长度为(1),那么下一步就可以使(S)(t)阶差分序列的每一位都为(0),即(t-1)阶差分序列的循环节长度为(1)

    于是,问题就转化为了求最小的(t),使(S)(t)阶差分序列的循环节长度为(1)

    但是,这还是没办法直接做。可以观察(S)(t)阶差分序列的第(i)(d_{t,i})为多少。容易得到:

    [large d_{t,i}=sum_{j=0}^t(-1)^jC_t^jS_{i-j} ]

    其中,下标是在模(len)意义下的。

    这就证明了为什么(len=P^k)时可以胜利,因为取(t=len),则(d_{t,i}=(1+(-1)^t)S_i=0)

    所以,可以考虑将(t)的初始值设为(0),每次给(t)加上(P^k),得到差分序列,然后检查循环节长度是否为(1)。如果为(1),就还原到这次操作之前的序列,并减小(k)

    时间复杂度(O(nPlog_Pn))

    code:

    #include<stdio.h>
    #include<memory.h>
    int a[300002],n,p,m,k,b[300002],c[300002],ans=2,pow[300002];
    int id(int val){return val<=0?val+m:val;}
    inline int mod(int val){return val>=p?val-p:val;}
    bool isloop(int len){
    	if(n%len)return 0;
    	for(int i=len+1;i<=n;i++)if(a[i]!=a[i-len])return 0;
    	return 1;
    }
    bool iseq(){
    	for(int i=2;i<=m;i++)if(a[i]!=a[i-1])return 0;
    	return 1;
    }
    int main(){
    	scanf("%d%d",&n,&p);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i]%=p;
    	for(m=1,k=0;m<=n&&!isloop(m);m=m*p,k++);
    	if(m>n)return puts("-1")&0;pow[0]=1;
    	for(int i=1;i<=k;i++)pow[i]=pow[i-1]*p;
    	if(iseq()){
    		if(a[1]==0)return puts("0")&0;
    		else return puts("1")&0;
    	}
    	for(int g=k-1;g>=0;g--){
    		for(int i=0;i<p-1;i++){
    			memcpy(c+1,a+1,sizeof(int)*m);
    			for(int i=1;i<=m;i++)a[i]=mod(c[i]+p-c[id(i-pow[g])]);
    			if(iseq()){
    				memcpy(a+1,c+1,sizeof(int)*m);
    				break;
    			}else ans+=pow[g];
    		}
    	}printf("%d",ans);
    }
    
  • 相关阅读:
    【InfoPath2007】The form has been closed
    深入浅出Nintex——调用子流程
    深入浅出Nintex——使用查询XML动作
    深入浅出Nintex——使用Call WebService来查询Item ID
    深入浅出Nintex——获得某群组的用户集合
    深入浅出SharePoint2007——Webpart开发
    深入浅出Nintex——获得指定用户的角色
    深入浅出Nintex——使用构建动态字符串动作
    Lucene.net 实现全文搜索
    DotLucene源码浅读笔记(1)补遗:编写简单中文分词器ChineseAnalyzer
  • 原文地址:https://www.cnblogs.com/ztc03/p/12364468.html
Copyright © 2011-2022 走看看