zoukankan      html  css  js  c++  java
  • SP422 TRANSP2

    挺神仙的置换题

    SP422 TRANSP2 - Transposing is Even More Fun 

    这个博客除了开始举例子别的都是对的:

    https://blog.csdn.net/BraketBN/article/details/50668414

    首先理解题意:

    就是单纯的矩阵转置,一行一行存储。

    (全部下标从0开始)

    一个位置(i,j)在转置后会变成(j,i)

    原来存储的位置是(下标从0开始):i*2^b+j

    现在是:j*2^a+i

    发现其实就是一个二进制数循环右移b位得到的

    向要到的位置连边,会形成K个置换环

    每个置换环内部换会len-1省一次

    总共就是:2^(a+b)-K

    关键是求K

    问题转化为:

    有2^(a+b)个元素

    两个元素是等价类当且仅当A循环右移b位和B相等

    求等价类的个数

    分母枚举所有的置换

    分子计算所有不动点的个数

    画画图,发现,在(a+b)的环上,一次走b步,最后有gcd(a,b)个置换环,和一次走gcd(a,b)步是一样的

    所以,可以这样写,然后反演:

    摘自:https://blog.csdn.net/BraketBN/article/details/50668414

    然后,2的次幂可以预处理,phi线性筛,d可以快速质因数分解,然后dfs枚举约数

    n直接求逆元,复杂度就是O(因子个数*T)

    代码:

    #include<bits/stdc++.h>
    #define reg register int
    #define il inline
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;x=0;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int mod=1000003;
    const int N=1e6+4;
    int vis[N],pri[N],phi[N],tot;
    int mindiv[N];
    int yin[1004],zhi[1004],cnt;
    void sieve(){
        phi[1]=1;
        for(reg i=2;i<=1e6;++i){
            if(!vis[i]){
                vis[i]=1;
                mindiv[i]=i;
                pri[++tot]=i;
                phi[i]=i-1;
            }
            for(reg j=1;j<=tot;++j){
                if(pri[j]*i>1e6) break;
                vis[pri[j]*i]=1;
                mindiv[i*pri[j]]=pri[j];
                if(i%pri[j]==0){
                    phi[i*pri[j]]=phi[i]*pri[j];
                    break;
                }else{
                    phi[i*pri[j]]=phi[i]*phi[pri[j]];
                }
            }
        }
    }
    ll ans;
    int pw[N];
    int g,n;
    void dfs(int x,int fac){
        if(x==cnt+1){
            ans=(ans+(ll)pw[fac*g]*phi[n/fac]%mod)%mod;
            return;
        }
        dfs(x+1,fac);
        int tmp=yin[x];
        for(reg i=1;i<=zhi[x];++i){
            dfs(x+1,fac*tmp);
            tmp=tmp*yin[x];
        }
    }
    int gcd(int a,int b){
        return b?gcd(b,a%b):a;
    }
    int qm(int x,int y){
        int ret=1;
        while(y){
            if(y&1) ret=(ll)ret*x%mod;
            x=(ll)x*x%mod;
            y>>=1;
        }
        return ret;
    }
    int main(){
        int t,a,b;
        sieve();
        pw[0]=1;
        for(reg i=1;i<=1e6;++i) pw[i]=(ll)pw[i-1]*2%mod;
        
        rd(t);
        while(t--){
            rd(a);rd(b);
            if(a==0||b==0){
                puts("0");continue;
            }
            g=gcd(a,b);
            n=(a+b)/gcd(a,b);
        //    cout<<" n "<<n<<endl;
            cnt=0;
            ans=0;
            
            int tmp=n;
            while(mindiv[tmp]){
                yin[++cnt]=mindiv[tmp];
                zhi[cnt]=0;
                while(mindiv[tmp]==yin[cnt]) tmp/=mindiv[tmp],++zhi[cnt];
            }
            dfs(1,1);
            
            ans=(ll)ans*qm(n,mod-2)%mod;
            ans=(qm(2,a+b)-ans+mod)%mod;
            printf("%lld
    ",ans);
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2019/2/18 11:31:26
    */

    总结:
    一个置换思想套置换本身的好题

    反演还过来凑凑热闹

  • 相关阅读:
    Myeclipse导出war包
    报表移动端如何进行移动设备绑定与撤销
    MySQL检查运行的mysqld服务器是否支持OpenSSL
    JavaScript替换字符串中最后一个字符
    dns 添加域名
    连接linux系统sftp下载文件
    8.1 Optimization Overview
    Chapter 8 Optimization
    19.6.1 Partitioning Keys, Primary Keys, and Unique Keys 分区键,主键,和唯一健
    Web报表页面如何传递中文参数
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10396141.html
Copyright © 2011-2022 走看看