DLUTOJ 1330 GCD 【莫比乌斯反演+组合】

http://acm.dlut.edu.cn/problem.php?id=1330

1330: GCD

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 22   Solved: 6
[ Submit][ Status][ Web Board]

Description

How many non decreasing sequences are there of length K, with the condition that numbers in sequence can take values only from 1,2,3,⋯N and gcd of all numbers in the sequence must be 1.

Input

The first line contains an integer T i.e. the number of test cases.
T lines follow, each line containing two integers N and K separated by a single space.
1≤T≤5 
1≤N≤10^5 
1≤K≤10^5

Output

For each testcase, print in a newline the answer mod(10^9+7).

Sample Input

42 4 3 45 21 10

Sample Output

413101

HINT

For the first testcase, the sequences are
(1,1,1,1), (1,1,1,2), (1,1,2,2), (1,2,2,2) = 4

For the second testcase, the sequences are
(1,1,1,1), (1,1,1,2), (1,1,1,3), (1,1,2,2), (1,1,2,3), (1,1,3,3)
(1,3,3,3), (1,2,2,2), (1,2,2,3), (1,2,3,3), (2,2,2,3), (2,2,3,3), (2,3,3,3)
which are 13 in number.

For the third testcase, the sequences are
(1,1), (1,2), (1,3), (1,4), (1,5), (2,3), (2,5), (3, 4), (3, 5), (4, 5) = 10

For the fourth testcase, the only sequence is
(1,1,1,1,1,1,1,1,1,1)

Source


k个数可选范围是1~n,问有多少个非降序列满足他们的gcd为1


令f(x)代表n以内, 长度为x的,满足题目要求且各个数字不相同的序列种类数。于是当k=4,n=3时,x=2时能够组成的种类数是f(2)*C(k-1,x-1)。即1112,1122,1222  3种*f(2)。所以下面只要求出f(x)的值便可得到答案。


假设需要选出x个不同的数字构成gcd=1的序列。g[d]代表长度为x的递增序列,其gcd=d的倍数 序列个数。g[d]容易看出是C(n/d,x),即从d的倍数中选出x个来组成序列。f[d]代表长度为x的递增序列,gcd=d时的情况,上面的f(x)默认下d为1,因而省略。于是可以知道g[d]=∑d|n f(n)  =C(n/d,x)

由莫比乌斯反演公式可得f(1)=∑1<=i<=n (mu[i]*g[i])

本体组合数需要预先处理,并且mu函数和可能出现负值,需要取正

//#include
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

#define For(i,a,b) for(int (i)=(a);(i) < (b);(i)++)
#define rof(i,a,b) for(int (i)=(a);(i) > (b);(i)--)
#define IOS ios::sync_with_stdio(false)
#define lson l,m,rt <<1
#define rson m+1,r,rt<<1|1
#define mem(a,b) memset(a,b,sizeof(a))

typedef long long ll;
typedef unsigned long long ull;


void RI (int& x){
    x = 0;
    char c = getchar ();
    while (c == ' '||c == '\n')    c = getchar ();
    bool flag = 1;
    if (c == '-'){
        flag = 0;
        c = getchar ();
    }
    while (c >= '0' && c <= '9'){
        x = x * 10 + c - '0';
        c = getchar ();
    }
    if (!flag)    x = -x;
}
void RII (int& x, int& y){RI (x), RI (y);}
void RIII (int& x, int& y, int& z){RI (x), RI (y), RI (z);}

/**************************************END define***************************************/
const int maxn = 1e5+10;
const int INF =0x3f3f3f3f;
const int mod = 1e9+7;
bool flag[maxn];
int mu[maxn];
vector prime;
ll A[maxn],inv[maxn],sum[maxn];
int n,k;
void get_prime_phi()
{
    mu[1]=1;
    For(i,2,maxn){
        if(!flag[i]){
            prime.push_back(i);
            mu[i]=-1;
        }
        for(int j=0;j>=1;
        a=a*a%mod;
    }
    return ans;
}

ll getC(int n,int m)
{
    //if(n


你可能感兴趣的:(数论)