Dividing Numbers
Time Limit: 9000/3000MS (Java/Others) Memory Limit: 262144/262144KB (Java/Others)
Submit Status
Given an integer N (1≤N≤1013) and K (1≤K≤100) co-prime numbers P1,P2,...,Pk, which are less than 1000. Please tell me how many integers in range [1,N] satisfied that none of a number in P1,P2,...,Pk can divide it.
Input
The first line contains two integers N (1≤N≤1013) and K (1≤K≤100).
The second line contains K numbers P1,P2,...,Pk. It is guaranteed that 2≤Pi≤1000.
It is guaranteed that the given K numbers are pairwise co-prime.
Output
Output an integer representing the number of integers in range [1,N] satisfied the condition.
Sample input and output
Sample Input | Sample Output |
---|---|
20 3 2 3 5 |
6 |
50 2 15 8 |
41 |
Source
2015 UESTC ACM Summer Training Team Selection (4)
结题报告:
注意到题目中的条件,两两互质,这是关键,即gcd( a , b ) = 1 , a, b ∈ array[p]
那么解决这道题的关键就在于重复数字的问题,例如 N = 105 , P = 3 , 5 , 那么15 , 30 , 45 .... 这几个数我们就必须保证只能删掉一次
我们令 F( i , j ) 表示范围[ 1 , i ] , 不能被P[0] , P[1] ..... P[j] 整除的数的个数
转移方程:
F ( i , j ) = F( i , j - 1 ) - F( i / p[j] , j - 1 )
转移方程的解释:
我们仅仅考虑P【j】这个数,能够被整数它的肯定是(1,2,3.... i / P[j] ) ,这些数很可能在以后(往前转移)经被筛过了,所以我们需要减去
反正过来想:
【1,N】之间不能被P【0】 -> P【j】 整数的数的数量 = 【1,N】之间不能被P【0】 -> P【j-1】 整除的数 - 【1,N】之间P【j】的因子数目(同时保证这些因子数目不是前面P【0】 -> P【j-1】 任何一个数的因子)
接下来的问题就是搜索了
因为N的范围很大,所以我们在小范围内使用记忆化搜索,大范围上用dfs即可
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <vector> #include <stack> #include <map> #include <set> #include <queue> #define pb push_back #define input_fast std::ios::sync_with_stdio(false);std::cin.tie(0) #define local freopen("in.txt","r",stdin) using namespace std; const int maxn = 5e4; long long n; int k , p[105]; long long f[maxn][105]; long long dfs(long long x,int y) { if (y == -1) return x; if (x < maxn) { if (f[x][y] != -1) return f[x][y]; return f[x][y] = dfs(x,y-1) - dfs(x/p[y],y-1); } else return dfs(x,y-1) - dfs(x/p[y],y-1); } int main(int argc,char *argv[]) { scanf("%lld%d",&n,&k); memset(f,-1,sizeof(f)); for(int i = 0 ; i < k ; ++ i) scanf("%d",&p[i]); sort(p,p+k); printf("%lld\n",dfs(n,k-1)); return 0; }