zoukankan      html  css  js  c++  java
  • SD 一轮集训 day3 染色(color)

         蜜汁打表题、、

    (首先L=1和L=N的情况过于傻逼(而且是特殊情况),可以先写出来,然后剩下的L的做法在下面)

         首先你要写一个打表程序,找出{1,2,....,n} 乘若干个 循环唯一的轮换可以搞出的所有排列,然后统计一下对于每个i,总环数=i 的排列的个数 cnt[i]。

         如果你规律找的好的话,是可以发现如下结论的:

              1.当L是偶数的时候,cnt[i] = s(N,i) ,其中s(,)是第一类斯特林数。

              2.当L是奇数的时候,cnt[i] = s(N,i) or 0,cnt[i]不为0当且仅当i和N的奇偶性相同。

         模数不是998244353.。。。这可怎么算斯特林数啊???

         但我们不需要把每个斯特林数都算出来啊。。。因为 最后 cnt[i] 要乘上 k^i 加入到答案里,然后有一个第一类斯特林数的公式 : k的n次上升幂 = Σ s(n,i) * k^i。

         简单来说这个公式可以总结为: 上升幂等于第一类斯特林数点积幂。

         然后L是偶数就可以直接带进去用置换的公式算了,是奇数的话要把k' = -k,带进去类似的算一下和或者差就好啦。

    /*
        x的n阶上升幂 = s(n,i) * x^i 
    */
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<queue>
    #include<vector>
    #define ll long long
    using namespace std;
    const int ha=1e9+7,maxn=2e6;
    inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x;}
    inline void ADD(int &x,int y){ x+=y; if(x>=ha) x-=ha;}
    
    inline int ksm(int x,int y){
    	int an=1;
    	for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;
    	return an;
    }
    
    int jc[maxn+5],ni[maxn+5],pre[maxn/2+5];
    int N,K,L,ans,d[2333],phi[2333],num;
    
    inline int C(int x,int y){ return x<y?0:jc[x]*(ll)ni[y]%ha*(ll)ni[x-y]%ha;}
    
    inline void init(){
    	jc[0]=1;
    	for(int i=1;i<=maxn;i++) jc[i]=jc[i-1]*(ll)i%ha;
    	ni[maxn]=ksm(jc[maxn],ha-2);
    	for(int i=maxn;i;i--) ni[i-1]=ni[i]*(ll)i%ha;
    }
    
    inline int getp(int x){
    	int an=1;
    	for(int i=2;i*(ll)i<=x;i++) if(!(x%i)){
    		x/=i,an*=i-1;
    		while(!(x%i)) x/=i,an*=i;
    	}
    	return an*(x==1?1:x-1);
    }
    
    inline void solve1(){	
    	for(int i=1;i<=K;i++) pre[i]=C(N-L+i-1,i-1);
    	for(int i=K;i;i--) ADD(pre[i],ha-pre[i-1]);
    	
    	for(int i=1;i*(ll)i<=L;i++) if(!(L%i)){
    		d[++num]=i;
    		if(i*i!=L) d[++num]=L/i;
    	}
    	for(int i=1;i<=num;i++) phi[i]=getp(L/d[i]);
    	
    	for(int i=1;i<=num;i++) ADD(ans,ksm(K,d[i])%ha*(ll)phi[i]%ha);
    	
    	ans=ans*(ll)ksm(L,ha-2)%ha;
    }
    
    inline void solve2(){
    	if(!(L&1)) ans=ni[N]*(ll)jc[K+N-1]%ha*(ll)ni[K-1]%ha;
    	else{
    		int A=add(jc[N],N<=1)*(ll)ni[2]%ha;
    		if(!(N&1)) A=add(ha-A,jc[N]);
    		A=ksm(A,ha-2);
    		
    		int B=jc[K+N-1]*(ll)ni[K-1]%ha;
    		int C=N>K?0:jc[K]*(ll)ni[K-N]%ha*(ll)((N&1)?ha-1:1)%ha;
    		
    		if(N&1) ans=add(B,ha-C)*(ll)ni[2]%ha*(ll)A%ha;
    		else ans=add(B,C)*(ll)ni[2]%ha*(ll)A%ha; 
    	}
    }
     
    int main(){
    //	freopen("color.in","r",stdin);
    //	freopen("color.out","w",stdout);
    	
    	scanf("%d%d%d",&N,&K,&L);
    	
    	init();
    	
    	if(N==L) solve1();
    	else if(L==1) ans=ksm(K,N);
    	else solve2();
    	
    	printf("%d
    ",ans);
    	
    	return 0;
    }
    

      

  • 相关阅读:
    requirejs 第一个实例
    ionic + cordova 环境搭建
    免安装mysql配置
    ConcurrentHashMap
    volatile和synchronized
    zookeeper集群安装
    题目
    Nginx
    CountDownLatch
    自己总结
  • 原文地址:https://www.cnblogs.com/JYYHH/p/9169202.html
Copyright © 2011-2022 走看看