题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3441
题意:将一个A*A的方块分成若干个B*B的方块,满足A*A=k*B*B+1。有m种颜色为每个格子涂色。最后将K个B*B的方格连在剩下的一个格上。旋转后相同的视为相同。有多少种不用的造型?
思路:(1)求出所有的B。分解A+1和A-1。然后DFS搜索出B;
(2)先用m种颜色给B*B的格子染色,四种置换。得到不同的染色方案cnt;
(3)最后问题等介于用cnt种颜色给K个珠子的项链染色,不同的染色方案。
int prime[N],cnt,tag[N];
void init()
{
int i,j;
for(i=2;i<N;i++) if(!tag[i])
{
prime[cnt++]=i;
for(j=i+i;j<N;j+=i) tag[j]=1;
}
}
#define PII pair<i64,i64>
i64 n,m;
vector<PII> factor;
vector<PII> split(i64 n)
{
vector<PII> V;
int i;
for(i=0;i<cnt&&(i64)prime[i]*prime[i]<=n;i++) if(n%prime[i]==0)
{
i64 cnt=0;
while(n%prime[i]==0) cnt++,n/=prime[i];
V.pb(MP(prime[i],cnt));
}
if(n>1) V.pb(MP(n,1));
return V;
}
vector<PII> unionFactor(vector<PII> a,vector<PII> b)
{
int i,j;
FOR0(i,SZ(b))
{
i64 x=b[i].first;
i64 y=b[i].second;
FOR0(j,SZ(a)) if(x==a[j].first)
{
a[j].second+=y;
break;
}
if(j>=SZ(a)) a.pb(MP(x,y));
}
return a;
}
i64 ans;
i64 tempAns;
i64 phi(i64 n)
{
i64 ret=1,i;
for(i=0;i<SZ(factor)&&sqr(factor[i].first)<=n;i++)
{
i64 x=factor[i].first;
if(n%x==0)
{
n/=x;ret*=x-1;
while(n%x==0) n/=x,ret*=x;
}
}
if(n>1) ret*=n-1;
return (ret%mod);
}
void dfs(int dep,i64 curI,i64 cnt,i64 K)
{
if(dep==SZ(factor))
{
tempAns+=myPow(cnt,curI,mod)*phi(K/curI)%mod;
tempAns%=mod;
return;
}
dfs(dep+1,curI,cnt,K);
i64 x=factor[dep].first;
i64 y=factor[dep].second;
i64 i;
FOR0(i,y)
{
curI*=x;
if(K%curI) return;
dfs(dep+1,curI,cnt,K);
}
}
void deal(i64 B)
{
i64 cnt=myPow(m,B*B,mod)+2*myPow(m,(B*B+3)/4,mod)+myPow(m,(B*B+1)/2,mod);
cnt%=mod;
cnt=cnt*gcdReverse(4,mod)%mod;
i64 K=(n-1)*(n+1)/(B*B);
tempAns=0;
dfs(0,1,cnt,K);
tempAns=tempAns*gcdReverse(K,mod)%mod;
ans=(ans+tempAns)%mod;
}
void DFS(int dep,i64 curB)
{
if(dep==SZ(factor))
{
deal(curB);
return;
}
DFS(dep+1,curB);
i64 x=factor[dep].first;
i64 y=factor[dep].second;
if(y>=2)
{
i64 i;
for(i=2;i<=y;i+=2)
{
factor[dep].second-=i;
DFS(dep+1,curB*myPow(x,i/2));
factor[dep].second+=i;
}
}
}
int main()
{
init();
int num=0;
rush()
{
scanf("%I64d%I64d",&n,&m);
if(n==1)
{
printf("Case %d: %I64d\n",++num,m);
continue;
}
factor.clear();
factor=unionFactor(split(n+1),split(n-1));
sort(factor.begin(),factor.end());
ans=0;
DFS(0,1);
ans=ans*m%mod;
printf("Case %d: %I64d\n",++num,ans);
}
}