zoukankan      html  css  js  c++  java
  • 【题解】「LibreOJ β Round #7」某少女附中的体育课

    题目链接

    题目大意:定义(m)进制下的运算符(oplus),它满足交换律,结合律,循环律,给出它在任意位上的其运算规则(A_{i,j}),表示(ioplus j=A_{i,j}),从([0,m^n))中以一定概率选出(k+1)个数(s_0,s_2dots,s_k),求([0,m^n))中每个数恰好等于(s_0oplus s_1oplusdotsoplus s_k)的概率。对(232792561=2^4 imes3^2 imes5 imes7 imes11 imes13 imes17 imes19)取模。

    神题啊,我看了两天题解才看懂

    首先,根据标签,可以想到题目是要让你构造一个变换及其逆变换,使得原概率序列(p_0,p_1,dots,p_{m^n-1})经该变换后,对每一位求(k)次方后再进行逆变换可以得到答案序列。

    于是可以设变换矩阵为(T),则有(p imes T)(q imes T)对应位置相乘后与((p*q) imes T)相等,即(T_{k,i} imes T_{k,j}=T_{k,ioplus j})

    因为该运算满足循环律,设满足(i^j=i(j>1))的最小的(j)(len_i),类比( ext{DFT})的转移矩阵,可以猜测(T_{i,j})(0)(len_j-1)次单位根的([0,len_j-1))次幂。

    然后就可以根据前面的规律(O(m^m))加剪枝来爆搜出此矩阵,求逆得逆变换矩阵,再对(p)进行变换,就可以得到目标数组。

    具体(神仙)证明

    code:

    #include<stdio.h>
    #include<algorithm>
    #define inf 232792561
    int a[102][202],ts[102],st[102],l=0;
    int p[102][102],q[102][102],w[102][102],t[102][102];
    int n,m;long long k;
    int A[1048576],B[1048576];
    inline int ksm(long long a,long long b){int ans=1;while(b)(b&1)&&(ans=a*ans%inf),a=a*a%inf,b>>=1;return ans;}
    inline void gs(int n,int m){
    	for(int i=0;i<n;i++){
    		int pos=i;
    		while(pos<n&&!a[pos][i])pos++;
    		if(pos>=n)exit(-1);
    		if(pos!=i)
    			for(int j=i;j<m;j++)
    				a[i][j]^=a[pos][j]^=a[i][j]^=a[pos][j];
    		int val=ksm(a[i][i],inf-2);
    		for(int j=i;j<m;j++)a[i][j]=1ull*val*a[i][j]%inf;
    		for(int j=0;j<n;j++)
    			if(i!=j&&a[j][i])
    				for(int k=m-1;k>=i;k--)
    					a[j][k]=(1ull*(inf-a[j][i])*a[i][k]+a[j][k])%inf;
    	}
    }
    void dfs(int pos){
    	if(l==m)return;
    	if(pos==m){
    		for(int i=0;i<m;i++)p[l][i]=st[i];
    		l++;return;
    	}bool ff=st[pos]=0;
    	for(int i=0;i<pos;i++){
    		for(int j=i;j<pos;j++){
    			if(t[i][j]==pos){
    				if(!ff)st[pos]=1ll*st[i]*st[j]%inf,ff=1;
    				else if(st[pos]!=1ll*st[i]*st[j]%inf)return;
    			}
    		}
    	}if(ff){
    		for(int j=0;j<=pos;j++){
    			if(t[j][pos]<=pos&&1ll*st[j]*st[pos]%inf!=st[t[j][pos]])return;
    		}dfs(pos+1);
    	}
    	else{
    		for(int i=0;i<=ts[pos];i++){
    			st[pos]=w[ts[pos]][i];
    			bool f=1;
    			for(int j=0;j<=pos;j++){
    				if(t[j][pos]<=pos&&1ll*st[j]*st[pos]%inf!=st[t[j][pos]])f=0;
    			}if(f)dfs(pos+1);
    		}
    	}
    }
    void ntt(int a[],int b[],int n,bool typ){
    	int dt=n/m,p1,p2;
    	if(dt!=1)for(int i=0;i<n;i+=dt)ntt(a+i,b,dt,typ);
    	for(int i=0;i<n;i++)b[i]=0;
    	for(int i=0;i<m;i++)
    		for(int j=0;j<m;j++)
    			for(int k=0;k<dt;k++){
    				int p1=i*dt+k,p2=j*dt+k;
    				b[p1]=(1ll*a[p2]*(typ?q[i][j]:p[i][j])+b[p1])%inf;
    			}
    	for(int i=0;i<n;i++)a[i]=b[i];
    }
    int main(){
    	scanf("%d%d%lld",&n,&m,&k);
    	n=ksm(m,n);
    	for(int i=0;i<m;i++)
    		for(int j=0;j<m;j++)
    			scanf("%d",&t[i][j]);
    	for(int i=1;i<=m;i++){
    		w[i][0]=1;
    		if(i!=1)w[i][1]=ksm(71,(inf-1)/i);
    		for(int j=2;j<i;j++)
    			w[i][j]=1ll*w[i][j-1]*w[i][1]%inf;
    	}for(int i=0;i<m;i++){
    		int P=i;ts[i]=0;
    		while(1){
    			ts[i]++;
    			P=t[P][i];
    			if(P==i)break;
    		}
    	}dfs(0);
    	for(int i=0;i<m;i++)
    		for(int j=0;j<m;j++)
    			a[i][j]=p[i][j];
    	for(int i=0;i<m;i++)
    		a[i][i+m]=1;
    	gs(m,m+m);
    	for(int i=0;i<m;i++)
    		for(int j=0;j<m;j++)
    			q[i][j]=a[i][j+m];
    	for(int i=0;i<n;i++)scanf("%d",&A[i]);
    	ntt(A,B,n,0);
    	for(int i=0;i<n;i++)A[i]=ksm(A[i],k+1);
    	ntt(A,B,n,1);
    	for(int i=0;i<n;i++)printf("%d
    ",A[i]);
    }
    
  • 相关阅读:
    ionic localstorage
    angular 中文鏈接
    把jqmobi 變成jQuery 的插件 從此使用jQuery
    jqmobi 的一些設置
    ionic ngcordova map 地圖
    ionic pull to refresh 下拉更新頁面
    json 對象的序列化
    鍵盤彈出,頁面佈局被推上去了.....
    Cordova V3.0.0中config.xml配置文件的iOS Configuration
    android ios 只能輸入數字 不能輸入小數點的 函數 cordova
  • 原文地址:https://www.cnblogs.com/ztc03/p/11964881.html
Copyright © 2011-2022 走看看