Codeforces 900D Unusual Sequences

题目链接

https://codeforces.com/contest/900/problem/D

题目大意

给你 X 、Y,让你构造一个序列a满足 gcd(a1, a2, ..., an) = x 并且 $\sum ^{n}_{i=1}a_{i}=y$

求满足条件的序列个数

解题思路

很显然当 Y % X != 0 时是无法构造出系列满足条件的

当 Y % X == 0 时,我们可以将条件建转换一下

即构造序列a满足gcd(a1, a2, ..., an) = 1 并且  $\sum ^{n}_{i=1}a_{i}=y/x$

那么如果只看条件②,我们用隔板法可以得到的构造方案为 $\sum ^{n}_{i=1}a_{i}=y/x$  参见这里

然后我们再看条件①,因为构造出来的部分答案可能会改变gcd,所以我们只要再把改变gcd的情况减掉就可以了

举个栗子: X = 3 , Y = 12  ,  那么改变条件之后 X = 1 , Y = 4。假设 solve(y / x) 得到的是当 gcd = x , sum = y 的构造方案

那么这个栗子的答案就为 solve(4 / 1)  - solve(4 / 2)  

AC_Coder

#include<bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define int long long
#define ll long long 
#define MOD 1000000007
using namespace std;
ll pow_mod(ll x , ll n , ll mod)
{
    ll res = 1;
    while(n)
    {
        if(n & 1) res = res * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return res;
}
const int N = 2e5 + 10;
unordered_map<int , int>vis;
int dfs(int n)
{
    if(n == 1) return 1;
    if(vis[n]) return vis[n];
    vis[n] = pow_mod(2 , n - 1 , MOD) - 1;
    for(int i = 2 ; i * i <= n ; i ++)
    {
        if(n % i == 0)
        {
            vis[n] = (vis[n] - dfs(n / i) + MOD) % MOD;
            if(i * i != n) 
            vis[n] = (vis[n] - dfs(i) + MOD) % MOD;
        }    
    }    
    return vis[n];
} 
signed main()
{
    int x , y;
    cin >> x >> y;
    if(y % x) return cout << 0 << '\n' , 0;
    int ans = dfs(y / x);
    cout << ans << '\n';
    return 0;
}
posted @ 2020-06-01 17:00  GsjzTle  阅读(135)  评论(0编辑  收藏  举报