HDU

来源:互联网 发布:淘宝led散热片 编辑:程序博客网 时间:2024/06/03 03:39

题目:有一个A*A的正方形,拆成A*A个1*1的小正方形,然后组成k个B*B的正方形,而且剩下一个小正方形,也就是A*A=K*B*B+1。问中间的小正方形连到K个B*B正方形的形状有多少种,有C种颜色,旋转视为等价。

思路:A*A-1=(A-1)*(A+1),把A-1的质因子求出来,把A+1的质因子求出来,合并,然后枚举B,求出C种颜色下B的等价类的数目,然后把其当成颜色去染K个B的项链,中间还有个1。这道题要充分运用质因子来优化。

代码:

#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<algorithm>#include<ctime>#include<cstdio>#include<cmath>#include<cstring>#include<string>#include<vector>#include<map>#include<set>#include<queue>#include<stack>#include<list>#include<numeric>using namespace std;#define LL long long#define ULL unsigned long long#define INF 0x3f3f3f3f3f3f3f3f#define mm(a,b) memset(a,b,sizeof(a))#define PP puts("*********************");template<class T> T f_abs(T a){ return a > 0 ? a : -a; }template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}// 0x3f3f3f3f3f3f3f3fconst LL MOD=1000000007;const int maxn=4e4+50;bool isprime[maxn];int prime[maxn],tol;vector<LL> pri;LL fac[maxn][2],total;LL Inv4,Invk;LL A,C;void make_prime(int n){    for(int i=0;i<=n;i++)        isprime[i]=true;    isprime[0]=isprime[1]=false;    tol=0;    for(int i=2;i<=n;i++){        if(isprime[i])            prime[tol++]=i;        for(int j=0;j<tol;j++){            if(i*prime[j]<=n)                isprime[i*prime[j]]=false;            else                break;            if(i%prime[j]==0)                break;        }    }}LL pow_mod(LL a,LL b){    LL res=1;    a=a%MOD;    while(b){        if(b&1) res=res*a%MOD;        a=a*a%MOD;        b/=2;    }    return res;}LL get_pri(LL n){    for(int i=0;i<tol&&(LL)prime[i]*prime[i]<=n;i++){        if(n%prime[i]==0){            while(n%prime[i]==0){                n/=prime[i];                pri.push_back(prime[i]);            }        }    }    if(n>1) pri.push_back(n);}LL get_merge(){    sort(pri.begin(),pri.end());    total=0;    fac[total][0]=pri[0];    fac[total++][1]=1;    for(int i=1;i<pri.size();i++){        if(pri[i]==fac[total-1][0])            fac[total-1][1]++;        else{            fac[total][0]=pri[i];            fac[total++][1]=1;        }    }}LL Phi(LL n){    LL res=1;    for(int i=0;i<total&&fac[i][0]*fac[i][0]<=n;i++){        if(n%fac[i][0]==0){            n/=fac[i][0];            res=res*(fac[i][0]-1);            while(n%fac[i][0]==0){                n/=fac[i][0];                res=res*fac[i][0];            }        }    }    if(n>1) res=res*(n-1);    return res%MOD;}LL resA;void dfs_A(int i,LL num,LL col,LL K){    if(i==total){        resA=(resA+pow_mod(col,K/num)*Phi(num)%MOD)%MOD;        return;    }    for(int j=0;j<=fac[i][1];j++){//搜索K的因子        dfs_A(i+1,num,col,K);        num=num*fac[i][0];    }}LL get_A(LL col,LL K){    resA=0;    Invk=pow_mod(K,MOD-2);    dfs_A(0,1,col,K);    return resA*Invk%MOD*C%MOD;}LL get_B(LL B){    LL ans=pow_mod(C,B*B);    ans=(ans+(LL)2*pow_mod(C,(B*B+3)/4)%MOD)%MOD;    ans=(ans+pow_mod(C,(B*B+1)/2)%MOD)%MOD;    return ans*Inv4%MOD;}LL ans;void dfs_B(int i,LL num){    if(i==total){        LL col=get_B(num);        LL K=(A*A-1)/num/num;        ans=(ans+get_A(col,K))%MOD;        return;    }    LL tmp=fac[i][1];    for(int j=0;j<=tmp;j+=2,fac[i][1]-=2){        dfs_B(i+1,num);        num=num*fac[i][0];    }    fac[i][1]=tmp;}int main(){    int T,cas=0;    make_prime(maxn-50);    Inv4=pow_mod((LL)4,MOD-2);    scanf("%d",&T);    while(T--){        scanf("%lld%lld",&A,&C);        if(A==1){            printf("Case %d: %lld\n",++cas,C);            continue;        }        ans=0;        pri.clear();        get_pri(A-1);        get_pri(A+1);        get_merge();//        PP;//        for(int i=0;i<total;i++)//            printf("%lld %lld\n",fac[i][0],fac[i][1]);//        PP;        dfs_B(0,1);        printf("Case %d: %lld\n",++cas,ans);    }    return 0;}


原创粉丝点击