zoukankan      html  css  js  c++  java
  • JZOJ1898. 【2010集训队出题】密码系统

    Description

    • Lambda受任于某情报站,他的工作是获取敌人情报。一次他在破解密码系统时,得到了一个N位B进制数φ,满足φ≡V (mod M)。他发现组成φ的数字很奇特。为了验证φ的特殊性,他将所有模M为V的N位B进制数,按照各数位构成的集合分类,并想知道每一类数各有多少个。
      在这里插入图片描述

    Solution

    • 不难想到矩乘,枚举所选集合再进行矩乘,f[i]表示余数为i的方案数,但是这样并不能保证集合中的都被选了,所以实际算出来需要容斥一下。
    • 再考虑矩乘的复杂度,如果直接M3是会爆的。但是我们发现将i和j合并起来时转移到的状态是一定的并且可以算出来,所以M2转移就好了。
    • 为什么这题这么特殊呢?
    • 我们一般的矩乘要枚举起点终点,而这题却枚举起点和终点间的转移,并且显然转移比那个枚举地更少更好。所以说这种情况仅当转移状态十分好枚举地时候才适用。
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #define maxm 125
    #define mo 10007
    using namespace std;
    
    int n,B,M,V,S,T,i,j,k,p;
    int f[maxm],ff[maxm],g[maxm],gg[maxm];
    int F[1<<11];
    
    int main(){
    	scanf("%d%d%d%d",&n,&B,&M,&V);
    	for(S=1;S<1<<B;S++){
    		memset(f,0,sizeof(f));
    		memset(g,0,sizeof(g));
    		for(i=0;i<B;i++) if ((S>>i)&1) g[i%M]++;
    		for(i=1;i<B;i++) if ((S>>i)&1) f[i%M]++;
    		p=B%M;
    		for(k=n-1;k;k/=2){
    			if (k&1){
    				memset(ff,0,sizeof(ff));
    				for(i=0;i<M;i++) if (f[i]) for(j=0;j<M;j++) if (g[j])
    					(ff[(i*p+j)%M]+=f[i]*g[j])%=mo;
    				memcpy(f,ff,sizeof(ff));
    			}
    			memset(gg,0,sizeof(gg));
    			for(i=0;i<M;i++) if (g[i]) for(j=0;j<M;j++) if (g[j])
    				(gg[(i*p+j)%M]+=g[i]*g[j]%mo)%=mo;
    			memcpy(g,gg,sizeof(gg));
    			p=p*p%M;
    		}
    		F[S]=f[V];
    		for(T=0;T<S;T++) if ((T&S)==T) 
    			F[S]=(F[S]-F[T]+mo)%mo;
    		for(i=B-1;i>=0;i--) if ((S>>i)&1) printf("%d",i);
    		printf(" %d
    ",F[S]);
    	}
    }
    
  • 相关阅读:
    【Nginx+Tomcat】高性能负载均衡的Tomcat集群
    【JS-Excel】使用JS导出表格数据、附带解决科学计数法等问题
    【Util】日期工具类总结
    【SpringMVC】url映射传参
    【Linux+Windows】Linux,Windows打包发布到Tomcat并修改映射的ip地址
    【Spring】解决返回json乱码问题
    【API】高德地图API JS实现获取坐标和回显点标记
    ELK-Python(二)
    ELK-Python(一)
    zookeeper集群
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/11700909.html
Copyright © 2011-2022 走看看