- 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∑pabi
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
题目来源
这一道题目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;
}