加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

HDU 2865 Birthday Toy

发布时间:2020-12-14 05:18:10 所属栏目:大数据 来源:网络整理
导读:题目链接 题意:n个小圆组成的正n边形,中间有一个大圆。有木棍相连的两个圆不能有相同的颜色,旋转后相同视为相同的方案,求着色方案数。 () 先选定一种颜色放在中间,剩下的 (k-1) 种颜色再摆在环上。下面直接令 (k=k-1) 。 根据Burnside引理, (

题目链接

题意:n个小圆组成的正n边形,中间有一个大圆。有木棍相连的两个圆不能有相同的颜色,旋转后相同视为相同的方案,求着色方案数。

()

先选定一种颜色放在中间,剩下的(k-1)种颜色再摆在环上。下面直接令(k=k-1)

根据Burnside引理,(ans=sum_{a|n}f(a)phi(frac{n}{a}))(f(a))表示最多使用(k)种颜色且长度为(a)的,首尾以及相邻珠子颜色互不相同的方案数。计算(f(n))时,假设(n-1)号珠子与(1)号珠子相同,则对答案的贡献为((k-1)cdot f(n-2));若不同,贡献为((k-2)cdot f(n-1))。所以(f(n)=(k-1)cdot f(n-2)+(k-2)cdot f(n-1))。用矩阵快速幂就好了。

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 1000005
#define mod 1000000007

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

ll n,k;
int p[N];
bool vis[N];

void pre(int n) {
    for(int i=2;i<=n;i++) {
        if(!vis[i]) p[++p[0]]=i;
        for(int j=1;j<=p[0]&&1ll*i*p[j]<=n;j++) {
            vis[i*p[j]]=1;
            if(i%p[j]==0) break;
        }
    }
}

int phi(int n) {
    ll ans=n;
    for(int i=1;1ll*p[i]*p[i]<=n;i++) {
        if(n%p[i]==0) ans=(ans-ans/p[i]);
        while(n%p[i]==0) n/=p[i];
    }
    if(n>1) ans=(ans-ans/n);
    return ans;
}

struct matrix {
    ll f[2][2];
    void Init() {memset(f,sizeof(f));}
}tem,g,t;

matrix operator *(const matrix &a,const matrix &b) {
    tem.Init();
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
                (tem.f[i][j]+=a.f[i][k]*b.f[k][j])%=mod;
    return tem;
}

matrix ksm(matrix g,int x) {
    matrix ans;
    ans.Init();
    for(int i=0;i<2;i++) ans.f[i][i]=1;
    for(;x;x>>=1,g=g*g)
        if(x&1) ans=ans*g;
    return ans;
}

ll ksm(ll t,ll x) {
    ll ans=1;
    for(;x;x>>=1,t=t*t%mod)
        if(x&1) ans=ans*t%mod;
    return ans;
}

ll cal(ll n) {
    if(n==1) return 0;
    matrix ans=t*ksm(g,n-2);
    return ans.f[0][1];
}

int main() {
    pre(1000000);
    while(scanf("%lld%lld",&n,&k)!=EOF) {
        g.f[0][0]=0,g.f[0][1]=k-2;
        g.f[1][0]=1,g.f[1][1]=k-3;
        t.f[0][0]=0,t.f[0][1]=(k-1)*(k-2)%mod;
        
        ll ans=0;
        for(int i=1,maxx=sqrt(n);i<=maxx;i++) {
            if(n%i==0) {
                (ans+=cal(i)*phi(n/i)%mod)%=mod;
                if(i*i!=n) (ans+=cal(n/i)*phi(i)%mod)%=mod;
            }
        }
        ans=ans*ksm(n,mod-2)%mod;
        ans=ans*k%mod;
        cout<<ans<<"n";
    }
    return 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读