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; }
凡所不能将我击倒的,都将使我更加强大