Spare Tire
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{
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
题目来源
ACM-ICPC 2018 沈阳赛区网络预赛
题意:
已知 ai a i 序列,给你一个n和m求小于n与m互质的数作为a序列的下标的和
分析:
通过打表发现
ai
a
i
序列就等于
ai=i(i+1)
a
i
=
i
(
i
+
1
)
那么原问题可以转化为求解
因此可以使用容斥定理得到
因为 i(i+1)=i2+i i ( i + 1 ) = i 2 + i
那么后面部分怎么求和呢
我们发现实际上就是找到mn的某个公因数d,然后就是倍数求和嘛
假设最小公因数为d,那么就是
这样我们可以将m进行素因子分解,然后二进制枚举组合出所有本质不同的最小的公因数,然后套用上式再利用容斥定理求解
code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const ll inv6 = 166666668;
const ll inv2 = 500000004;
ll a[10005];
ll clac(ll n,ll i){
n /= i;
return (n % mod * (n + 1) % mod * (2 * n + 1) % mod * inv6 % mod * i % mod * i % mod + n % mod * (n + 1) % mod * inv2 % mod * i % mod) % mod;
}
int main(){
ll n,m;
while(~scanf("%lld%lld",&n,&m)){
int cnt = 0;
for(int i = 2; i * i <= m; i++){
if(m % i == 0){
a[cnt++] = i;
while(m % i == 0)
m /= i;
}
}
if(m != 1)
a[cnt++] = m;
ll ans = clac(n,1);
ll ans2 = 0;
for(int i = 1; i < (1 << cnt); i++){
int flag = 0;
ll tmp = 1;
for(int j = 0; j < cnt; j++){
if(i & (1 << j)){
flag++;
tmp = tmp * a[j] % mod;
}
}
tmp = clac(n,tmp);
if(flag & 1) ans2 = (ans2 % mod + tmp % mod) % mod;
else ans2 = (ans2 % mod - tmp % mod + mod) % mod;
}
printf("%lld\n",(ans % mod - ans2 % mod + mod) % mod);
}
return 0;
}