26 分解质因子 容斥 数学公式

  • 15.41%
  • 1000ms
  • 131072K

A sequence of integer {an}\lbrace a_n \rbrace{an​} can be expressed as:

an={0,n=02,n=13an−1−an−22+n+1,n>1\displaystyle a_n = \left\{ \begin{array}{lr} 0, & n=0\\ 2, & n=1\\ \frac{3a_{n-1}-a_{n-2}}{2}+n+1, & n>1 \end{array} \right. an​=⎩⎨⎧​0,2,23an−1​−an−2​​+n+1,​n=0n=1n>1​

Now there are two integers nnn and mmm. I'm a pretty girl. I want to find all b1,b2,b3⋯bpb_1,b_2,b_3\cdots b_pb1​,b2​,b3​⋯bp​ that 1≤bi≤n1\leq b_i \leq n1≤bi​≤n and bib_ibi​ is relatively-prime with the integer mmm. And then calculate:

∑i=1pabi\displaystyle \sum_{i=1}^{p}a_{b_i} i=1∑p​abi​​

But I have no time to solve this problem because I am going to date my boyfriend soon. So can you help me?

Input

Input contains multiple test cases ( about 150001500015000 ). Each case contains two integers nnn and mmm. 1≤n,m≤1081\leq n,m \leq 10^81≤n,m≤108.

Output

For each test case, print the answer of my question(after mod 1,000,000,0071,000,000,0071,000,000,007).

Hint

In the all integers from 111 to 444, 111 and 333 is relatively-prime with the integer 444. So the answer is a1+a3=14a_1+a_3=14a1​+a3​=14.

样例输入

4 4

样例输出

14

题目来源

ACM-ICPC 2018 沈阳赛区网络预赛

这一道题目get到很多知识点

1, 一个长整型的数字最多有10个质数因子,并且这个数字分解的次数不会超过40,

2,对于在某个数范围内与该数字互质,或是不互质的数字我们利用这个数字的质

      因子将这个数字不互质的数字全部组合起来,我们利用这个组合起来的数字作

      为等差数列的首项然后在进行往下推算,可以采用o(1)的时间复杂度将以这个数

      为首项的等差数列的和给求出来,但是我们在求算的时候可能会算重复,需要

      容斥一下;

3,就是两个公式等差数列的前n项和,和平方项(1*1 +2*2 + 3*3 + 4*4...+n*n)的

     和是 ((n)*(n+1)*(2*n+1))  /  6;

    对于这一道题目我们假 设  n=6,  m=6 ;的话我们有下面的求算规则;

4 ,还有就是怎么求算逆元  pow(x,mod-2) ;

n              :       1         2         3         4         5          6

m质因子 :      2        3            等差数列首项          数列的长度

组合 1      :       0         0                     6                         6/6(1)   ( 加上 )

        2      :       0         1                      3                        6/3(3,6) (减掉)

        3      :       1          0                     2                        6/2(2,4,6) (减掉)

        4     :      1         1                     6                        6/6(1)         (加上 )//因为我们这里把6的计算相应的减掉了两次所以要加上

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int Max =  1e8;
const int mod =  1e9+7;
const int Max1 = 1e5+10;
#define rep(i,s,n)  for(ll i=s;i<=n;i++)
#define per(i,n,s)  for(ll i=n;i>=s;i--)
int p[10000];
ll num1;
ll pow1(ll base , ll k){
  ll res=1;
  while(k){
    if(k&1) res=res*base%mod;
    base=base*base%mod;
    k>>=1;
  }
  return (res%mod+mod)%mod;
}
int main(){
    //前n个数字的平方和1+2*2+3*3........+n*n=n*(n+1)*(2*n+1)/6;
    ll n6=pow1(6,mod-2)%mod;
    ll n2=pow1(2,mod-2)%mod;
    ll n,m;
   while(scanf("%lld %lld",&n,&m)!=EOF){
    ll tmp=m;
    num1=0;
    ll s=0;
    for(ll i=2;i*i<=tmp;i++){//求算某一个数的所有质因数;e18的数据最多是40次就可以
        if(tmp%i==0){//处理完毕;
            p[num1++]=i;
            while(tmp%i==0){
                tmp/=i;
            }
        }
    }//某一个数字的质因子最多不会超过10个;
    if(tmp>1) p[num1++]=tmp;
    ll sum=0,base,cnt,num;
    num1=(1<<num1);
    rep(i,0,num1-1){//枚举所有的质因数可以直接求得的等差数列的首项
      cnt=0;//然后后面减掉这个首项的整数倍;就是一个等差数列的平方和和一个等差数列求和;
      ll ans=i;
      ll len=0;
      base=(ll)1;
      while(ans){
        if(ans%2==1){
            base=base*p[len]%mod;
            cnt++;
        }
        ans/=2;
        len++;
      }
      num=n/base;//求算在n这个区间内部,有多少个数是base的倍数;
      ll res=(num)%mod*(num+1)%mod;//等差数列的平方和求算;
      res=res*(2*num%mod+1)%mod;
      res=(res*n6)%mod;
      res=(res*base)%mod;
      res=(res*base)%mod;
      ll res1=(base%mod+num*base%mod)%mod*num%mod;//仅仅是等差数列求和;
      res1=(res1*n2)%mod;
      res=(res+res1)%mod;
      if(cnt%2==0) sum=(sum+res)%mod,s+=num;
      else sum=(sum-res)%mod,s-=num;//这个地方是容斥,如果是我们采用了奇数个
      sum=(sum%mod+mod)%mod;
      //printf("%lld\n",s);
    }
    printf("%lld\n",(sum%mod+mod)%mod);
    //printf("%lld\n",s);
   }
   return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39792342/article/details/82533693