[spoj244]Transposing is Even More Fun 解题报告

来源:互联网 发布:美女图片源码带采集 编辑:程序博客网 时间:2024/05/29 16:45

拿这题学了一下Burnside’s引理。
模型转换:考虑坐标二进制,转置其实就是将其旋转b位,那么求圈数就转换为了求轨道数。
然后就直接裸上Burnside’s引理即可。
但是。。一个巨大的hack是——注意到数据范围:0a+b106,a+b为0时除(a,b)可能就re了。所以要特判a==0||b==0时的情况,这时答案为0.

#include<cstdio>#include<iostream>using namespace std;#include<cmath>#include<cstring>#include<algorithm>typedef long long LL;const int C=4e5+5,A=1e6+5;const int Mod=1000003;int prime[1000005],phi[1000005],smp[1000005];int gcd(int a,int b){    return b?gcd(b,a%b):a;}LL pow(int a,int x){    LL ans=1,prod=a;    for(;x;x>>=1,prod=prod*prod%Mod)        if(x&1)            ans=ans*prod%Mod;    return ans;}LL power[1000005];int ind[25],dvs[25];int n;int ans;void dfs(int x,int d){//d0*d1=a+b    if(x<0){        ans=(ans+power[d]*phi[n/d])%Mod;        //cout<<d<<":"<<power[d]*phi[n/d]%Mod<<endl;        return;    }    dfs(x-1,d);    for(int i=ind[x];i;--i)dfs(x-1,d*=dvs[x]);}void in(int &x){    char c=getchar();    while(c<'0'||c>'9')c=getchar();    for(x=0;c>='0'&&c<='9';c=getchar())x=x*10+(c^'0');}int main(){    freopen("transp2.in","r",stdin);    //freopen("transp2.out","w",stdout);    phi[1]=smp[1]=1;    for(int i=2;i<=1000000;++i){        if(!phi[i]){            prime[++prime[0]]=smp[i]=i;            phi[i]=i-1;        }        for(int j=1;j<=prime[0]&&i*prime[j]<=1000000;++j){            smp[i*prime[j]]=prime[j];            if(i%prime[j])phi[i*prime[j]]=phi[i]*(prime[j]-1);            else{                phi[i*prime[j]]=phi[i]*prime[j];                break;            }        }    }    power[0]=1;    for(int i=1;i<=1000000;++i)power[i]=(power[i-1]<<1)%Mod;    int g,a,b,c,tot;    in(c);    while(c--){        //puts("-------");        in(a),in(b);        if(a==0||b==0){            puts("0");            continue;        }        ans=0;        n=a+b,g=gcd(n,b),n/=g;        //cout<<g<<" "<<n<<endl;        tot=0;        for(tot=0;n!=1;++tot){            dvs[tot]=smp[n],ind[tot]=0;            for(;smp[n]==dvs[tot];n/=smp[n])++ind[tot];        }        /*for(int i=tot;i--;)cout<<dvs[i]<<"^"<<ind[i]<<"*";        puts("");*/        n=a+b;        dfs(tot-1,g);        printf("%d\n",((power[n]-ans*pow(n/g,Mod-2))%Mod+Mod)%Mod);    }}

总结:
①遇到2x这种形式时,可以考虑2进制。
②一定要注意数据的范围:最小值、最大值和0、1、-1或其他特殊数据是否会存在。

0 0
原创粉丝点击