URAL 1091 Tmutarakan Exams

题意

N 以内的大小为K的数集个数,满足数集内的数的 gcd>1

题解

设f[x]表示公约数是x的倍数的情况数,g[x]表示公约数恰好是x的情况数
有:
fn=n|dg(d)
gn=n|df(d)μ(dn)
其中 fn=(Ndk)

gn=2nNn|d(Ndk)μ(dn)

交换后
gn=d(Ndk)n|dμ(dn)[n2]

注意到二项式系数当 dN 时为 0 ,故
gn=1dN(Ndk)([n==1]μ(d))


gn=2dN(Ndk)

code

#include<cstdio>
#include<cstring>

typedef long long LL;

const int maxn=1010;
const int maxp=1010;

int prime[maxp],primeN;
int phi[maxn], mu[maxn];
LL sphi[maxn];int smu[maxn];
bool isprime[maxn];
void gen(int n) {
    primeN = 0;
    memset(isprime, 1, sizeof isprime);

    isprime[0]=isprime[1]=0;
    phi[1]=1, mu[1]=1;
    for(int i=2,p;i<n;++i){
        if (isprime[i]) {
            prime[primeN ++]=p=i;
            phi[p]=p-1, mu[p]=-1;
        }

        for(int j=0,x;j<primeN && (x=i*(p=prime[j]))<n;++j){
            isprime[x] = 0;

            if(!(i%p)){
                phi[x]=phi[i]*p, mu[x]=0;
                break;
            } else {
                phi[x]=phi[i]*(p-1), mu[x]=-mu[i];
            }
        }
    }
}

const int MAXN=60;
int K,N;
LL C[MAXN][MAXN];

int main(){
//  freopen("in.txt","r",stdin);
    scanf("%d%d",&K,&N);

    gen(N+1);
    for(int i=0;i<=N;++i){
        C[i][0]=C[i][i]=1;
        for(int j=1;j<i;++j)
            C[i][j]=C[i-1][j]+C[i-1][j-1];
    }

    LL res=0;

    for(int d=1;d<=N;++d)
        res+=C[N/d][K]*((d==1) - mu[d]);

/*  for(int n=2;n<=N;++n)
        for(int d=n;d<=N;++d)if(d%n==0)
            res+=C[N/d][K]*mu[d/n];
*/  
    printf("%d\n",res<=10000 ? res : 10000);
//  for(;;);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值