zoukankan      html  css  js  c++  java
  • bzoj1547 周末晚会

    我们要求方案数,还是旋转同构的,想burnside,如果我们能计算出转i位不变的满足条件的数量,那么这道题我们就解决了。

    考虑转i位时,设tmp=gcd(i,n),那么就共有tmp个循环节。

    当tmp<=k时,只要不是所有的循环节都是女生就可以,所以数量为2^tmp-1,但是要特判k>=n,因为这时所有方案都满足条件。

    当tmp>k时,我们需要在提前处理出符合条件的且旋转不变的方案数,考虑dp,我们设f[i][j]表示长度为i的线段第一位是男生,末尾有且仅有j位女生的满足条件的方案,g[i][j]与f相同,只是不限首位。h[i]表示环的,就是线段的去掉首尾相加大与k的,这里注意中间的区间位置不唯一。

    最后直接上burnside就好了!

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #define int long long
     7 #define N 2050
     8 #define mod 100000007
     9 using namespace std;
    10 int T,n,m,ans;
    11 int f[N][N],g[N][N],h[N],s[N],pw[N];
    12 int qp(int a,int b){
    13     int c=1;
    14     while(b){
    15         if(b&1)c=c*a%mod;
    16         a=a*a%mod; b>>=1;
    17     }return c;
    18 }
    19 int gcd(int a,int b){return !b?a:gcd(b,a%b);}
    20 signed main(){
    21     scanf("%lld",&T);
    22     pw[0]=1;
    23     for(int i=1;i<=2000;i++)pw[i]=(pw[i-1]<<1)%mod;
    24     while(T--){
    25         ans=0;
    26         scanf("%lld%lld",&n,&m);
    27         f[1][0]=s[1]=1;f[1][1]=0;
    28         for(int i=2;i<=n;i++){
    29             f[i][0]=s[i]=s[i-1];
    30             for(int j=1;j<=m&&j<i;j++){
    31                 f[i][j]=f[i-1][j-1];
    32                 (s[i]+=f[i][j])%=mod;
    33             }
    34         }
    35         g[0][0]=s[0]=1;
    36         for(int i=1;i<=n;i++){
    37             g[i][0]=s[i]=s[i-1];
    38             for(int j=1;j<=m&&j<=i;j++){
    39                 g[i][j]=g[i-1][j-1];
    40                 (s[i]+=g[i][j])%=mod;
    41             }
    42             h[i]=s[i];
    43             for(int j=m+1;j<=2*m&&j<i;j++)
    44                 h[i]=(h[i]-(f[i-j][0]*max((int)0,min(j-1,m)-max((int)1,j-m)+(int)1))%mod+mod)%mod;
    45         }
    46         for(int i=1;i<=n;i++){
    47             int tmp=gcd(i,n);
    48             if(tmp<=m){
    49                 if(m>=n)ans=(ans+pw[tmp])%mod;
    50                 else ans=(ans+pw[tmp]-1+mod)%mod;
    51             }
    52             else ans=(ans+h[tmp])%mod;
    53         }
    54         ans=ans*qp(n,mod-2)%mod;
    55         printf("%lld
    ",ans);
    56     }
    57     return 0;
    58 }
    View Code
  • 相关阅读:
    【Language】 TIOBE Programming Community Index for February 2013
    【diary】good health, good code
    【web】a little bug of cnblog
    【Git】git bush 常用命令
    【web】Baidu zone ,let the world know you
    【diary】help others ,help yourself ,coding is happiness
    【Git】Chinese messy code in widows git log
    【windows】add some font into computer
    SqlServer启动参数配置
    关于sqlserver中xml数据的操作
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/8467451.html
Copyright © 2011-2022 走看看