BZOJ 3202 项链

题目连接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3202

题意:一个项链由n个珠子组成。每个珠子有三个面,每个面上有一个数字,要求每个珠子三个面的数字的Gcd值为1。三个数排序后相同的算作一种,即珠子(1,3,4)和珠子(3,1,4)是一样的。每个面的数字范围为[1,a]。项链中相邻珠子不能相同,旋转后相同的算作一种。求不同的项链个数。模M=1e9+7。

思路:首先可以算出不同珠子的种类,容斥莫比乌斯啥的,设有m种。接下来设长度为n的项链满足相邻不一样的方案数,设为f(n),那么f(n)=f(n-1)*(m-2)+f(n-1)*(m-2)。这样答案为:

const i64 M1=1000000007;
const i64 M2=1000000014000000049;
const int N=10000005;

int prime[N],cnt,tag[N];
int mou[N];

void init()
{
    int i,j;
    for(i=2;i<N;i++)
    {
        if(!tag[i]) prime[cnt++]=i,mou[i]=-1;
        for(j=0;j<cnt&&(i64)i*prime[j]<N;j++)
        {
            tag[i*prime[j]]=1;
            if(i%prime[j]) mou[i*prime[j]]=-mou[i];
            else
            {
                mou[i*prime[j]]=0;
                break;
            }
        }
    }
    mou[1]=1;
}

i64 n,a,mod;

i64 mul(i64 x,i64 y)
{
    x%=mod;
    i64 ans=0;
    if(y<0) x=-x,y=-y;
    while(y)
    {
        if(y&1) ans=(ans+x)%mod;
        x=(x+x)%mod;
        y>>=1;
    }
    if(ans<0) ans+=mod;
    return ans;
}

i64 C2(i64 x)
{
    if(x<2) return 0;
    return x*(x-1)/2%mod;
}

i64 C3(i64 x)
{
    if(x<3) return 0;
    i64 a=x,b=x-1,c=x-2;
    if(a%2==0) a>>=1;
    else b>>=1;

    if(a%3==0) a/=3;
    else if(b%3==0) b/=3;
    else c/=3;

    return mul(mul(a,b),c);
}

i64 cal()
{
    i64 ans=1;
    int i;
    for(i=1;i<=a;i++) if(mou[i])
    {
        ans+=mou[i]*C2(a/i)*2;
        ans%=mod;
        ans+=mou[i]*C3(a/i);
        ans%=mod;
    }
    return ans;
}

i64 myPow(i64 x,i64 y)
{
    i64 ans=1;
    while(y)
    {
        if(y&1) ans=mul(ans,x);
        x=mul(x,x);
        y>>=1;
    }
    return ans;
}

i64 m;

i64 eular(i64 x)
{
    i64 i;
    i64 ans=x;
    for(i=0;i<cnt&&(i64)prime[i]*prime[i]<=x;i++) if(x%prime[i]==0)
    {
        ans-=ans/prime[i];
        while(x%prime[i]==0) x/=prime[i];
    }
    if(x>1) ans-=ans/x;
    return ans;
}

i64 f(i64 n)
{
    if(n%2==0) return (myPow(m-1,n)+(m-1))%mod;
    return (myPow(m-1,n)-(m-1))%mod;
}

int main()
{
    init();
    int T=getInt();
    while(T--)
    {
        n=getInt();
        a=getInt();

        if(n%M1==0) mod=M2;
        else mod=M1;

        m=cal();

        i64 ans=0;
        int i;
        for(i=1;(i64)i*i<=n;i++) if(n%i==0)
        {
            ans+=mul(f(i),eular(n/i));
            ans%=mod;
            if(n/i!=i) ans+=mul(f(n/i),eular(i));
            ans%=mod;
        }
        if(mod==M1) ans=mul(ans,myPow(n%mod,mod-2));
        else
        {
            mod=M1;
            ans=ans/mod*myPow(n/mod,mod-2)%mod;
        }

        if(ans<0) ans+=mod;
        printf("%lld\n",ans);
    }
}
时间: 2024-10-12 15:41:07

BZOJ 3202 项链的相关文章

bzoj 3202 [Sdoi 2013] 项链 —— 置换+计数

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3202 参考了博客: https://www.cnblogs.com/zhoushuyu/p/9657640.html https://www.cnblogs.com/DUXT/p/5957944.html?utm_source=itdadao&utm_medium=referral https://blog.csdn.net/Maxwei_wzj/article/details/83184

【BZOJ】【1878】【SDOI2009】HH的项链

树状数组/前缀和 Orz lct1999 好神的做法... 先看下暴力的做法:对于区间[l,r],我们依次扫过去,如果这个数是第一次出现,那么我们种类数+1. 我们发现:区间中相同的几个数,只有最左边那个才对答案有贡献. 那么我们O(n)预处理一个next数组,满足a[i]=a[next[i]],且i~next[i]这一段中没有与a[i]相等的数....其实就是 i 右边第一个跟a[i]相等的值的下标啦.. 再回头看下我们的询问:对答案有贡献的数的特点是:它在整个序列中第一次出现,或者它是区间外

【BZOJ】【3790】神奇项链

Manacher算法/DP 找出所有的回文串,看做是一个个线段,那么问题就转化成了用最少的线段将整个区间覆盖起来,可以重叠,那么这就是一个DP了= = Orz ZKY大爷,让蒟蒻开眼界了……头一次知道原来树状数组还可以反过来用0.0 1 /************************************************************** 2 Problem: 3790 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6

BZOJ 3790 神奇项链 hash/后缀自动机+贪心

Description 母亲节就要到了,小 H 准备送给她一个特殊的项链.这个项链可以看作一个用小写字母组成的字符串,每个小写字母表示一种颜色. 为了制作这个项链,小 H 购买了两个机器.第一个机器可以生成所有形式的回文串,第二个机器可以把两个回文串连接起来,而且第二个机器还有一个特殊的性质:假如一个字符串的后缀和一个字符串的前缀是完全相同的,那么可以将这个重复部分重叠.例如:aba和aca连接起来,可以生成串abaaca或 abaca. 现在给出目标项链的样式,询问你需要使用第二个机器多少次才

洛谷 P1972 BZOJ 1878 [SDOI2009]HH的项链

题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链变得越来越长.有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同的贝壳?这个问题很难回答……因为项链实在是太长了.于是,他只好求助睿智的你,来解决这个问题. 输入输出格式 输入格式: 第一行:一个整数N,表示项链的长度. 第二行:N 个整数,表示依次表示项链中贝壳的编号(编号为0 到1000000 之间

[BZOJ 1878] [SDOI2009] HH的项链

题目链接: BZOJ - 1878 题目分析 题目的询问是某个区间内的颜色种类数,所以我们希望这个区间内的每种颜色只被计数一次,那么我们就选取询问区间内的每种颜色第一次出现的元素计数,之后再出现已经在询问区间中出现过的颜色就不再计数.考虑一种离线算法,如果我们将所有询问按照询问区间的左端点排序,那么所有询问的左端点就是不递减的,一直向右推移.开始时预处理出每个元素后面第一个与它颜色相同的元素是哪一个,并将所有出现的颜色的第一个元素加入到树状数组中.那么开始时维护的区间就是从 1 开始的.每次处理

bzoj 1878 [SDOI2009]HH的项链(离线处理+BIT)

Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此, 他的项链变得越来越长.有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同 的贝壳?这个问题很难回答...因为项链实在是太长了.于是,他只好求助睿智的你,来解 决这个问题. Input 第一行:一个整数N,表示项链的长度. 第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的

【BZOJ [1878】[SDOI2009]HH的项链

Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步 完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此, 他的项链变得越来越长.有一天,他突然提出了一个问题:某一段贝壳中,包含了多少种不同 的贝壳?这个问题很难回答...因为项链实在是太长了.于是,他只好求助睿智的你,来解 决这个问题. Input 第一行:一个整数N,表示项链的长度. 第二行:N个整数,表示依次表示项链中贝壳的编号(编号为0到1000000之间的

BZOJ 1878: [SDOI2009]HH的项链( BIT )

离线处理 , 记下询问的左右端点并排序 , 然后可以利用树状数组 , 保证查询区间时每种颜色只计算一次 ------------------------------------------------------------------------------------------------ #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define