[bzoj3202][SDOI2013]项链

题目大意

现在有一个由n个珠子组成的项链,满足相邻两个珠子不同。
每个珠子可以看做三个数组成的序列,需要满足三个数最大公约数为1且每个数不大于m,两个珠子如果经过旋转或翻转完全一致则认为其相同。
现在求不同项链数,两个项链如果经过旋转完全一致则认为其相同。
答案模10^9+7.
n<=10^14,m<=10^7

题解

太麻烦了看Crazy的吧
Crazy的项链题解
程序我写的比较优美所以贴我的。
注意n比模数大,但注意到n的因子中最多只含有一个模数。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const ll maxn=10000000+10;
const ll mo=1000000007;
ll pri[maxn],miu[maxn],sum[maxn],c[maxn];
bool bz[maxn];
ll i,j,k,l,t,m,ca,top,tot,cnt;
ll n,p,t2,t3,ans,b[maxn];
ll quicksortmi(ll x,ll y){
    if (!y) return 1;
    ll t=quicksortmi(x,y/2); t=t*t%mo; if (y%2) t=t*x%mo; return t; } ll f(ll n){ ll t=(cnt-1)*quicksortmi(-1,n)%mo; t=(t+mo)%mo; t=(t+quicksortmi(cnt-1,n))%mo; return t; } void dfs(ll x,ll y,ll z){ if (x==tot+1){ ans=(ans+f(n/y)*(z%mo)%mo)%mo; //printf("%lld\n",ans); return; } dfs(x+1,y,z); ll i; ll j=1; fo(i,1,c[x]){ j*=b[x]; dfs(x+1,y*j,z*j/b[x]*(b[x]-1));
    }
}
int main(){
    miu[1]=sum[1]=1;
    fo(i,2,maxn-10){
        if (!bz[i]) pri[++top]=i,miu[i]=-1;
        fo(j,1,top){
            if ((ll)i*pri[j]>maxn-10) break;
            bz[i*pri[j]]=1;
            if (i%pri[j]==0){
                miu[i*pri[j]]=0;
                break;
            }
            miu[i*pri[j]]=-miu[i];
        }
        sum[i]=sum[i-1]+miu[i];
    }
    scanf("%lld",&ca);
    while (ca--){
        scanf("%lld%lld",&n,&m);
        p=n;
        tot=0;
        fo(i,1,top){
            if (p==1) break;
            if (p%pri[i]==0){
                b[++tot]=pri[i];
                c[tot]=0;
                while (p%pri[i]==0){
                    p/=pri[i];
                    c[tot]++;
                }
            }
        }
        if (p>1) b[++tot]=p,c[tot]=1;
        //p=mo*mo;
        t3=t2=0;
        i=1;
        while (i<=m){
            j=m/(m/i);
            t3=(ll)(t3+(ll)(m/i)*(m/i)%mo*(m/i)%mo*(sum[j]-sum[i-1])%mo)%mo;
            t3=(ll)(t3+mo)%mo;
            t2=(ll)(t2+(ll)(m/i)*(m/i)%mo*(sum[j]-sum[i-1])%mo)%mo;
            t2=(ll)(t2+mo)%mo;
            i=j+1;
        }
        cnt=(ll)(t3+3*t2%mo+2)*quicksortmi(6,mo-2)%mo;
        ans=0;
        dfs(1,1,1);
        if (n%mo==0) ans=ans*quicksortmi(n/mo,mo-2)%(mo*mo)/mo%mo;
        else{
            n%=mo;
            ans=ans*quicksortmi(n,mo-2)%mo;
        }
        ans=(ans%mo+mo)%mo;
        printf("%lld\n",ans);
    }
}

你可能感兴趣的:([bzoj3202][SDOI2013]项链)