【SPOJ419】Transposing is Fun Pólya定理+欧拉函数

【SPOJ419】Transposing is Fun

题意:给你一个$2^a\times2^b$的矩阵,将$1...n$中的数依次从左到右,从上往下填到矩阵里,再把矩阵转置,然后把所有数从左到右,从上往下拿出来得到一个新的排列$A$。你现在每次可以交换两个数,问你从$1...n$变成排列$A$最少要进行多少次操作。
询问次数$\le400000,a+b\le 10^6$
题解:首先我们可以找到所有的循环节,如果一个循环节中有$x$个数,需要交换$x-1$次。所以我们只需要求出循环节的个数$k$,那么答案就是$2^{a+b}-k$。
如何求出循环节的个数呢?假设$a=5,b=3$,考虑元素$(12,1)$,其二进制表示为$(01010,001)$,它原来的位置是$01010?001$,新位置是$001?01010$。相当于将每个数的位置二进制向右移动$b$位。
所以,我们可以令$gcd(a,b)=g$,将$g$个数分成一组,相当于用$2^g$种颜色去染$a+b\over g$个珠子,就又变成了上面那题。
依旧要用欧拉函数优化,同POJ2154。

#include <cstring>
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const ll P=1000003;
const int N=2000000;
int T,a,b,n,m,g,num;
ll ans;
ll pw[N+10];
int cnt[100],p[100];
int phi[N+10],np[N+10],pri[N],xp[N+10],mn[N+10];
inline ll pm(ll x,int y)
{
    ll z=1;
    while(y)
    {
        if(y&1) z=z*x%P;
        x=x*x%P,y>>=1;
    }
    return z;
}
int gcd(int a,int b)
{
    return (!b)?a:gcd(b,a%b);
}
void dfs(int x,int d)
{
    if(x==m+1)
    {
        ans=(ans+pw[g*d]*phi[n/d])%P;
        return ;
    }
    for(int i=0;i<=cnt[x];i++,d*=p[x])  dfs(x+1,d);
}
inline void init()
{
    phi[1]=1;
    int i,j,p;
    for(pw[0]=i=1;i<=N;i++) pw[i]=(pw[i-1]<<1)%P;
    for(i=2;i<=N;i++)
    {
        if(!np[i])  pri[++num]=i,mn[i]=i,xp[i]=1,phi[i]=i-1;
        for(j=1;j<=num&&i*pri[j]<=N;j++)
        {
            p=pri[j],np[i*p]=1,mn[i*p]=p;
            if(i%p==0)
            {
                phi[i*p]=phi[i]*p,xp[i*p]=xp[i]+1;
                break;
            }
            phi[i*p]=phi[i]*(p-1),xp[i*p]=1;
        }
    }
}
inline void work()
{
    scanf("%d%d",&a,&b),ans=m=0;
    if(!a||!b)
    {
        puts("0");
        return ;
    }
    g=gcd(a,b),n=(a+b)/g;
    int t=n;
    while(t!=1)
    {
        p[++m]=mn[t],cnt[m]=xp[t];
        while(mn[t]==p[m])  t/=p[m];
    }
    dfs(1,1);
    printf("%lld\n",(pw[a+b]-ans*pm(n,P-2)%P+P)%P);
}
int main()
{
    init();
    scanf("%d",&T);
    while(T--)  work();
    return 0;
}//1 2 30000

原文地址:https://www.cnblogs.com/CQzhangyu/p/8227370.html

时间: 2024-07-30 05:15:33

【SPOJ419】Transposing is Fun Pólya定理+欧拉函数的相关文章

【poj2154】Color Polya定理+欧拉函数

题目描述 $T$ 组询问,用 $n$ 种颜色去染 $n$ 个点的环,旋转后相同视为同构.求不同构的环的个数模 $p$ 的结果. $T\le 3500,n\le 10^9,p\le 30000$ . 题解 Polya定理+欧拉函数 根据 poj2409 中得到的结论,答案为: $\frac{\sum\limits_{i=1}^nn^{\gcd(i,n)}}n=\sum\limits_{i=1}^nn^{\gcd(i,n)-1}$ 由于 $n$ 有 $10^9$ 之大,因此考虑优化这个式子. 枚举

Polya 定理入门[Burnside引理,Polya定理,欧拉函数]

$这篇blog重点讨论Polya的应用, 更详细的证明请百度 .$ ___ $Burnside引理$ $$L=\frac{1}{|G|}\sum_{i=1}^{|G|}D(a_i)$$ $L$: 本质不同的方案数. $G$: 置换群集合. $a_i$: 置换群中的第 $i$ 个置换. $D(a_i)$: 进行 $a_i$ 这个置换, 状态不会变化的方案 数量. 该引理与下方内容没有太大关系, 可以暂时忽略. ___ $Problem$ 链接 有 $N$ 个石子围成一圈, 使用 $M$ 种颜色染色

费马小定理,欧拉函数

在证明这些定理之前先证明一个有意思的定理. 对于0 mod m,n mod m , 2n mod m, 3n mod m, 4n mod m... (m-1)n mod m 对应解集序列 一定有 m/d份 0 d 2d 3d..m-d. (不一定按照顺序) 这样的解. 其中d = gcd(n,m) 具体点:n=8,m=12.  d = gcd(n,m)=4 对于 0 mod 12,8 mod 12,16 mod 12,24 mod 12,32 mod 12,40 mod 12...88 mod

poj2054Color polya定理+欧拉函数优化

没想到贱贱的数据居然是错的..搞得我调了一中午+晚上一小时(哦不d飞LJH掉RP毕竟他是BUFF)结果重判就对了五次.. 回归正题,这题傻子都看得出是polya定理(如果你不是傻子就看这里),还没有翻转,就一个旋转,结果我就欢快的打完交上去了.傻子都知道会TLE,n<=1e9啊,O(n)都原地爆炸,那怎么办...一脸懵逼(然后就膜题解了) 可以发现,这题公式就是sigma(gcd(k,n))(k=1~n),然后该怎么优化呢,我(??)发现gcd(k,n)里面肯定有一些k和n的gcd是相同的,那我

【日常学习】乘法逆元&amp;&amp;欧拉定理&amp;&amp;费马小定理&amp;&amp;欧拉函数应用&amp;&amp;常大学霸

转载请注明出处 [ametake版权所有]http://blog.csdn.net/ametake欢迎来看看 今天花了一个多小时终于把乘法逆元捣鼓明白了 鉴于我拙计的智商抓紧把这些记录下来 在此本栏目鸣谢里奥姑娘和热心网友himdd的帮助和支持 那么正文开始··· 逆元是干什么的呢? 因为(a/b)mod p ≠(a mod p)/(b mod p) 我们需要想一种方法避免高精 那就是把除法转化为乘法 因为(a*b) mod p = ( a mod p ) *( b mod p ) 怎么转化呢?

BZOJ-1951-古代猪文-SDOI2010-费马小定理+欧拉函数+lucas定理+中国剩余定理

描述 =>G∑(ni),i|nmodP 分析 k=∑Cin,i|n(modP) G?(P)≡1(modP),?(p)=p?1 P′=P?1 =>GP′≡1(modP) Gk≡GkmodP′(modP) 如何求k? lucas定理 (nm)=(nmodP′mmodP′)?(n/P′m/P′) P'不是素数, lucas定理不适用. 所以把P'-1拆成2*3*4679*35617再用中国剩余定理来解. 一下子用这么多不熟悉的定理和方法感觉这个题好厉害. 终于知道当被模的数不是质数该怎么用中国剩余定

HDOJ M斐波那契数列 4549【矩阵快速幂+快速幂+费马小定理+欧拉函数】

M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 2096    Accepted Submission(s): 596 Problem Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给

Luogu4980 【模板】Polya定理(Polya定理+欧拉函数)

对于置换0→i,1→i+1--,其中包含0的循环的元素个数显然是n/gcd(i,n),由对称性,循环节个数即为gcd(i,n). 那么要求的即为Σngcd(i,n)/n(i=0~n-1,也即1~n).考虑枚举gcd.显然gcd(i,n)=x在该范围内解的个数是φ(n/x).分解一下质因数即可. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<c

费马小定理及欧拉函数

2016.1.26 对于m=p1e1 . p2e2 . p3e3 . …… . pnen 欧拉函数定义为φ(m)=m * ∏(pi – 1)/pi 其意义为不超过m并且和m互素的数的个数 特别的φ(1)=1 对于和m互素的x,有xφ(m)≡1(mod m) 特别的,当p为素数时,x无法被p整除,φ(p)=p-1,于是便有费马小定理Xp-1≡1(mod p) 在p是素数时,对任意正整数x都有Xp≡X(mod p) 于是对于a的逆元x,有ax≡1(mod m),对于a,m互素时,有x=am-2,于是