ACM-ICPC 2018 瀋陽賽區網路預賽 G.Spare Tire (容斥)
阿新 • • 發佈:2018-12-24
A sequence of integercan be expressed as:
Now there are two integers nn and mm. I’m a pretty girl. I want to find all that is relatively-prime with the integer . And then calculate:
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 15000 ). Each case contains two integers n and m.
.
Output
For each test case, print the answer of my question(after mod 1,000,000,007).
Hint
In the all integers from 1 to 4, 1 and 3 is relatively-prime with the integer 4. So the answer is a_1+a_3=14
樣例輸入 複製
4 4
樣例輸出 複製
14
題意
已知序列,給你一個n和m求小於n與m互質的數作為a序列的下標的和
思路
我們通過打表發現序列就等於 ,那麼原問題就可以轉換為求解
那我們可以考慮
又有
我們要是列舉m的素因子,那麼我們可以通過容斥找出中與m不互質的數,例如m的因子中含有2,那麼都是與m不互質的數,這些數的和我們可以提出一個2,然後數的長度就是,然後套用上面的求和公式即可,然後對不同的因子的貢獻再套用容斥模板即可,記得求和公式要用逆元
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
const long long mod=1e9+7;
long long a[10005];
long long inv6=166666668;
long long inv2=500000004;
long long clac(long long n,long long i)
{
n=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()
{
long long n,m;
while(scanf("%lld%lld",&n,&m)!=EOF)
{
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;
long long ans=clac(n,1);
long long ans2=0;
for(int i=1;i<(1<<cnt);i++)
{
int flag=0;
long long temp=1;
for(int j=0;j<cnt;j++)
if(i&(1<<j))
{
flag++;
temp=temp*a[j]%mod;
}
temp=clac(n,temp);
if(flag%2==1)
{
ans2=(ans2%mod+temp%mod)%mod;
}
else
ans2=(ans2%mod-temp%mod+mod)%mod;
}
printf("%lld\n",(ans%mod-ans2%mod+mod)%mod);
}
return 0;
}