Codeforces 900D Unusual Sequences

题目链接:https://codeforces.com/problemset/problem/900/D

题目:给定 x, y (1 <= x, y <= 1e9)  问有多少个序列满足   a1+a2+......+an = y  且 gcd(a1, a2, a3......, an) = x.  (ai > 0)

思路: 显然当 y%x != 0 时无解。然后问题就等价于将有多少个序列满足a1+a2+....+an = y/x 且 gcd = 1. 因为将n个东西分成任意多份,每一份都不能为空的分法有2^(t-1)种. (隔板法). 但此时不能保证gcd = 1.  但是我们可以枚举他的gcd(y/x 的因子)  再减去这些不符合的. 设f(p)代表gcd为p的倍数的方案个数则 f(p) = 2^((y/x)/p - 1),然后就可以容斥了.

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 3e4+5e3;
const ll mod = 1e9+7;

ll prime[maxn];
bool vis[maxn];
int cnt = 0;

void Prime() {
    memset(vis, false, sizeof vis);
    for(int i = 2; i < maxn; i++) {
        if(!vis[i])  prime[cnt++] = i*1ll;
        for(int j = 0; j < cnt && i*prime[j] < maxn; j++) {
            vis[i*prime[j]] = true;
            if(i % prime[j] == 0)  break;
        }
    }
}

int Mo(ll k) {
    if(k == 1)  return 1;
    int ans = 1;
    for(int i = 0; i < cnt && prime[i]*prime[i] <= k; i++) {
        int num = 0;
        while(k % prime[i] == 0) {
            k /= prime[i];
            num++;
        }
        if(num > 1)  return 0;
        if(num == 1)  ans *= -1;
    }
    if(k != 1)  return -ans;
}

ll pow_mod(ll p, ll k) {
    ll ans = 1;
    while(k) {
        if(k & 1)  ans = ans*p%mod;
        p = p*p%mod;  k >>= 1;
    }
    return ans;
}

int main() {
    Prime();
    ll x, y;
    scanf("%lld%lld", &x, &y);
    if(y % x != 0)  {
        printf("0\n");
        return 0;
    }
    y /= x;
    ll ans = 0;
    for(ll i = 1; i*i <= y; i++) {
        if(y % i == 0) {
            ans = ((ans+Mo(y/i)*pow_mod(2, i-1))%mod+mod)%mod;
            if(i*i != y)  ans = ((ans+Mo(i)*pow_mod(2, y/i-1))%mod+mod)%mod;
        }
    }
    printf("%lld\n", ans);
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值