UESTC_Dividing Numbers CDOJ 1156

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;
}
时间: 2024-10-16 09:28:24

UESTC_Dividing Numbers CDOJ 1156的相关文章

Hdu 1156

题目链接 Brownie Points II Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 207    Accepted Submission(s): 77 Problem Description Stan and Ollie play the game of Odd Brownie Points. Some brownie po

LeetCode OJ - Sum Root to Leaf Numbers

这道题也很简单,只要把二叉树按照宽度优先的策略遍历一遍,就可以解决问题,采用递归方法越是简单. 下面是AC代码: 1 /** 2 * Sum Root to Leaf Numbers 3 * 采用递归的方法,宽度遍历 4 */ 5 int result=0; 6 public int sumNumbers(TreeNode root){ 7 8 bFSearch(root,0); 9 return result; 10 } 11 private void bFSearch(TreeNode ro

129. Sum Root to Leaf Numbers

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. An example is the root-to-leaf path 1->2->3 which represents the number 123. Find the total sum of all root-to-leaf numbers. For example, 1 / 2 3 T

421. Maximum XOR of Two Numbers in an Array

Given a non-empty array of numbers, a0, a1, a2, - , an-1, where 0 ≤ ai < 231. Find the maximum result of ai XOR aj, where 0 ≤ i, j < n. Could you do this in O(n) runtime? Example: Input: [3, 10, 5, 25, 2, 8] Output: 28 Explanation: The maximum resul

Humble Numbers(丑数) 超详解!

给定一个素数集合 S = { p[1],p[2],...,p[k] },大于 1 且素因子都属于 S 的数我们成为丑数(Humble Numbers or Ugly Numbers),记第 n 大的丑数为 h[n]. 算法 1: 一种最容易想到的方法当然就是从 2 开始一个一个的判断一个数是否为丑数.这种方法的复杂度约为 O( k * h[n]),铁定超时(如果你这样做而没有超时,请跟 tenshi 联系) 算法 2: 看来只有一个一个地主动生成丑数了 : 我最早做这题的时候,用的是一种比较烂的

【Scala】Scala之Numbers

一.前言 前面已经学习了Scala中的String,接着学习Scala的Numbers. 二.Numbers 在Scala中,所有的数字类型,如Byte,Char,Double,Float,Int,Long,Short都是对象,这七种数字类型继承AnyVal特质,这七种数字类型与其在Java中有相同的范围,而Unit和Boolean则被认为是非数字值类型,Boolean有false和true两个值,你可以获取到各个数字类型的最值. 复杂的数字和日期 如果需要更强大的数类,可以使用spire,sc

2、Add Two Numbers

1.Add Two Numbers--这是leedcode的第二题: You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. Input:

[LeetCode In C++] 2. Add Two Numbers

题目: You are given two linked lists representing two non-negative numbers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. Input: (2 -> 4 -> 3) + (5 -> 6 -&

[LeetCode] Compare Version Numbers

Question: Compare two version numbers version1 and version2.If version1 > version2 return 1, if version1 < version2 return -1, otherwise return 0. You may assume that the version strings are non-empty and contain only digits and the . character.The