2018 ICPC 瀋陽網路賽 G. Spare Tire 1到n中與m互質的平方和與本身和
計蒜客
Spare Tire
編輯程式碼
- 15.27%
- 1000ms
- 131072K
A sequence of integer \lbrace a_n \rbrace{an} can be expressed as:
\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 nn and mm. I'm a pretty girl. I want to find all b_1,b_2,b_3\cdots b_pb1,b2,b3⋯bp that 1\leq b_i \leq n1≤bi≤n and b_ibiis relatively-prime with the integer mm. And then calculate:
\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 1500015000 ). Each case contains two integers nn and mm. 1\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,007).
Hint
In the all integers from 11 to 44, 11 and 33 is relatively-prime with the integer 44. So the answer is a_1+a_3=14a1+a3=14.
樣例輸入複製
4 4
樣例輸出複製
14
題目來源
由通項公式的遞推式得:an=n^2+n;
設S=1^2+2^2+.+n^2
(n+1)^3-n^3 = 3n^2+3n+1
n^3-(n-1)^3 = 3(n-1)^2+3(n-1)+1
...
..
...
2^3-1^3 = 3*1^2+3*1+1
把上面n個式子相加得:(n+1)^3-1 = 3* [1^2+2^2+...+n^2] +3*[1+2+.+n] +n
所以S= (1/3)*[(n+1)^3-1-n-(3/2)*n(n+1)] = (1/6)n(n+1)(2n+1)
n的前n項和顯而易見為n*(n+1)/2;
根據容斥定理:通過狀壓列舉n範圍內m的每個因子倍數的數量,顯而易見n範圍內m的因子和m不互素。我們可知m的因子y在n範圍內的倍數數量為 cnt = n /y; 所以與x有關的與m不互素的和為 y*y*cnt*(cnt+1)*(2*cnt+1)+y*cnt*(cnt+1)。
由容斥的基本思想我們可以知道;我們減去單個因子的倍數,同時也會把兩個因子的公倍數減去兩邊。所以我們還要加上兩個因子公倍數在n範圍內的倍數的和。
程式碼如下:
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int maxn = 1e8 + 10;
const LL mod = 1000000007;
int arr[maxn/10];
int p;
LL _pow(LL a,LL b)
{
LL res= 1;
while(b)
{
if(b&1) res=res*a%mod;
b=b>>1;
a=a*a%mod;
}
return res;
}
LL get(LL x, LL y) {
LL cnt = x / y;
return (y*y%mod*cnt%mod*(cnt+1)%mod*(2*cnt+1)%mod*_pow(6,mod-2)%mod + y*cnt%mod*(cnt+1)%mod*_pow(2,mod-2)%mod)%mod;
}
void getp(LL n) { //將要求預期互質的數因子分解
p = 0;
for(int i = 2; i * i <= n; i++) {
if(n % i == 0) {
arr[p++] = i;
while(n % i == 0)
n /= i;
}
}
if(n > 1) arr[p++] = n;
//printf("(%d)", p);
}
int main() {
LL n,m,sum;
while(scanf("%lld %lld", &n,&m) != EOF) {
LL ans = 0;
if( n == 1) {
sum=2;
printf("%lld\n", ((sum - ans)+mod)%mod);
continue;
}
getp(m);
sum =(n*(n+1)%mod*(2*n+1)%mod*_pow(6,mod-2)%mod + n*(n+1)%mod*_pow(2,mod-2)%mod)%mod;
for(int i = 1; i < (1 << p); i++) { //狀壓
LL res = 0, cnt = 1;
for(int j = 0; j < p; j++) {
if(i & (1 << j)) {
cnt *= arr[j];
res++;
}
}
if(res & 1){//容斥
ans += get(n, cnt);
ans%=mod;
}
else{
ans -= get(n, cnt);
ans=(ans+mod)%mod;
}
}
printf("%lld\n", ((sum - ans)+mod)%mod);
}
return 0;
}