zoukankan      html  css  js  c++  java
  • HNOI2008Cards

    看了一下polya和burnside定理,感觉还行(就是不会证……)

    这题用的是burnside

    ans=在每个置换群下不动的方案数之和除以置换数

    这题有个难点在取模

    关于对p(p为素数)取模(涉及到了除法),我总结了两种方法:

    已知x mop p=y,要求x/z mod p=?

    大体思路是利用乘法逆,将/z转换成*z的逆元即可

    一、利用费马小定理

         z^p-1 mod p=1 

         所以z的逆元=power_mod(z,p-2,p)

    二、利用拓展欧几里德算法,即exgcd(z,p,x,y) 

          while x<0 do inc(x,p)

          事实上,这也是乘法逆的思想

          exgcd(z,p,x,y) 这实际上是在解同余方程zx mod p=1

          x不就是z的逆元吗

    但是当p不是素数时,应该怎么办呢?

    在做noi2002robot的时候,我运用了一种特殊的方法,最后需要求x>>1 mod p=?

    我在过程中始终对p取模,到最后感觉做不下去了

    后来我灵机一动,想到了多取一位 在过程中mod 10p  

    这样 最后输出的时候再mod p 答案就正确了

    不知道这样的方法能否应用在更广泛的地方……

    ps:刚才试了一下此题

        在过程中一直对m*p取模,最后ans div m 再对p取模,竟然AC了 

        原理在哪里?

    代码:

    神牛Green Clouds 的代码(费马小定理):

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4  
     5 using namespace std ;
     6  
     7 const int maxn =21;
     8  
     9 int sr , sb , sg , m , mod , f[ maxn ][ maxn ][ maxn ], a[ maxn *3], n ;
    10 bool used[ maxn *3];
    11 int v[ maxn *3], cnt , ans =0;
    12  
    13 void update(int&num ,int val ){
    14     ( num += val )%= mod ;
    15 }
    16  
    17 int power(int val ,int times ){
    18     int rec =1;
    19     for(; times ; times >>=1){
    20         if( times &1)( rec *= val )%= mod ;
    21         ( val *= val )%= mod ;
    22     }
    23     return rec ;
    24 }
    25  
    26 int main(  ){
    27     scanf("%d%d%d%d%d",&sr ,&sb ,&sg ,&m ,&mod );
    28     n = sr + sb + sg ;
    29     for(int w =0; w ++< m +1;){
    30         if( w < m +1)for(int i =0; i ++< n ;)scanf("%d", a + i );
    31         else for(int i =0; i ++< n ;) a[ i ]= i ;
    32         memset( used ,false,sizeof( used ));
    33         cnt =0;
    34         for(int i =0; i ++< n ;)if(! used[ i ]){
    35             v[++ cnt ]=0;
    36             for(int j = i ;! used[ j ]; j = a[ j ]){
    37                 ++ v[ cnt ], used[ j ]=true;
    38             }
    39         }
    40         memset( f ,0,sizeof( f ));
    41         f[0][0][0]=1;
    42         for(int h =0; h ++< cnt ;){
    43             for(int i = sr ; i >=0;-- i ){
    44                 for(int j = sb ; j >=0;-- j ){
    45                     for(int k = sg ; k >=0;-- k ){
    46                         if( i >= v[ h ])update( f[ i ][ j ][ k ], f[ i - v[ h ]][ j ][ k ]);
    47                         if( j >= v[ h ])update( f[ i ][ j ][ k ], f[ i ][ j - v[ h ]][ k ]);
    48                         if( k >= v[ h ])update( f[ i ][ j ][ k ], f[ i ][ j ][ k - v[ h ]]);
    49                     }
    50                 }
    51             }
    52         }
    53         update( ans , f[ sr ][ sb ][ sg ]);
    54     }
    55     ( ans *=power( m +1, mod -2))%= mod ;
    56     printf("%d
    ", ans );
    57     return 0;
    58 }
    View Code 

    exgcd:

     1 var s1,s2,s3,n,m,p,ans,i,j,x,y:longint;
     2     a:array[0..70,0..70] of longint;
     3     f:array[0..25,0..25,0..25] of longint;
     4 function mo(x:longint):longint;
     5  begin
     6    mo:=x mod (p);
     7  end;
     8 procedure init;
     9  begin
    10    readln(s1,s2,s3,m,p);
    11    n:=s1+s2+s3;
    12    for i:=1 to m do
    13     for j:=1 to n do
    14      read(a[i,j]);
    15    inc(m);
    16    for i:=1 to n do a[m,i]:=i;
    17  end;
    18 function dp(x:longint):longint;
    19  var i,j,k,tot,y,h,num:longint;
    20      v:array[0..70] of boolean;
    21      d:array[0..70] of longint;
    22  begin
    23    tot:=0;
    24    fillchar(v,sizeof(v),false);
    25    for i:=1 to n do
    26     if not(v[i]) then
    27      begin
    28        num:=1;
    29        v[i]:=true;
    30        y:=i;
    31        while a[x,y]<>i do
    32         begin
    33          y:=a[x,y];
    34          v[y]:=true;
    35          inc(num);
    36         end;
    37        inc(tot);
    38        d[tot]:=num;
    39      end;
    40    fillchar(f,sizeof(f),0);
    41    f[0,0,0]:=1;
    42    for h:=1 to tot do
    43     for i:=s1 downto 0 do
    44      for j:=s2 downto 0 do
    45       for k:=s3 downto 0 do
    46        begin
    47         if i>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i-d[h],j,k]);
    48         if j>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i,j-d[h],k]);
    49         if k>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i,j,k-d[h]]);
    50        end;
    51    exit(f[s1,s2,s3]);
    52    end;
    53 procedure exgcd(a,b:longint;var x,y:longint);
    54  var t:longint;
    55  begin
    56  if a=1 then begin x:=1;y:=0;exit;end;
    57  exgcd(b,a mod b,x,y);
    58  t:=x;x:=y;y:=t-(a div b)*x;
    59  end;
    60 procedure main;
    61  begin
    62    ans:=0;
    63    for i:=1 to m do
    64     ans:=mo(ans+dp(i));
    65    exgcd(m,p,x,y);
    66    while x<0 do inc(x,p);
    67    writeln((ans*x) mod p);
    68  end;
    69 begin
    70   init;
    71   main;
    72 end.         
    View Code

    m*p:

     1 var s1,s2,s3,n,m,p,ans,i,j,x,y:longint;
     2     a:array[0..70,0..70] of longint;
     3     f:array[0..25,0..25,0..25] of longint;
     4 function mo(x:longint):longint;
     5  begin
     6    mo:=x mod (m*p);
     7  end;
     8 procedure init;
     9  begin
    10    readln(s1,s2,s3,m,p);
    11    n:=s1+s2+s3;
    12    for i:=1 to m do
    13     for j:=1 to n do
    14      read(a[i,j]);
    15    inc(m);
    16    for i:=1 to n do a[m,i]:=i;
    17  end;
    18 function dp(x:longint):longint;
    19  var i,j,k,tot,y,h,num:longint;
    20      v:array[0..70] of boolean;
    21      d:array[0..70] of longint;
    22  begin
    23    tot:=0;
    24    fillchar(v,sizeof(v),false);
    25    for i:=1 to n do
    26     if not(v[i]) then
    27      begin
    28        num:=1;
    29        v[i]:=true;
    30        y:=i;
    31        while a[x,y]<>i do
    32         begin
    33          y:=a[x,y];
    34          v[y]:=true;
    35          inc(num);
    36         end;
    37        inc(tot);
    38        d[tot]:=num;
    39      end;
    40    fillchar(f,sizeof(f),0);
    41    f[0,0,0]:=1;
    42    for h:=1 to tot do
    43     for i:=s1 downto 0 do
    44      for j:=s2 downto 0 do
    45       for k:=s3 downto 0 do
    46        begin
    47         if i>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i-d[h],j,k]);
    48         if j>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i,j-d[h],k]);
    49         if k>=d[h] then f[i,j,k]:=mo(f[i,j,k]+f[i,j,k-d[h]]);
    50        end;
    51    exit(f[s1,s2,s3]);
    52    end;
    53 procedure main;
    54  begin
    55    ans:=0;
    56    for i:=1 to m do
    57     ans:=mo(ans+dp(i));
    58    writeln((ans div m) mod p);
    59  end;
    60 begin
    61   init;
    62   main;
    63 end.   
    64     
    View Code
  • 相关阅读:
    Python将字符串转换成字典
    MySQL索引、视图
    MySQL高级查询
    MySQL函数应用
    MySQL约束
    MySQL基础查询
    MySQL数据库基本语法
    MySQL数据库存储引擎
    MySQL数据库简介与命令行操作
    MySQL 安装和配置环境变量
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/3799170.html
Copyright © 2011-2022 走看看