SRM 500(2-1000pt)
DIV2 1000pt
题意:给定两个集合A和B,A = {b1*q1i | 0 <= i <= n1-1},B = {b2*q2i | 0 <= i <= n2-1},问将AB两个集合合并之后的集合中元素的个数。(注意,每个集合中每个元素只能有一个)。其中0 <= b1,b2,q1,q2 <= 5*10^8,1 <= n1,n2 <= 10^5。
解法:首先,我们称b = 0或者q = 0或者q = 1的集合为特殊集合,因为特殊集合中最多有两个元素。若至少有一个集合为特殊集合,则此问题容易解决。下面考虑两个集合都不为特殊集合的情况。
其实,如果不是A和B中的数太大,我们可以将他们每个都求出来,然后放到一个set<long long>里面,返回set.size()即可,时间复杂度O(n1 + n2)。我们需要找到一种表示这些大数的方法。考虑整数的唯一分解式。
每个整数可以表示成(a1^p1) * (a2^p2) * (a3^p3) *..* (ak^pk)的形式,也就是说,我们只需要统一所有会用到的质数,然后把p1,p2..pk放到一个vector里面,就可以表示每个整数。然后用一个set<vector<long long> >即可统计元素的个数。
tag: math, set
// BEGIN CUT HERE
/*
* Author: plum rain
* score :
*/
/* */
// END CUT HERE
#line 11 "GeometricProgressions.cpp"
#include <sstream>
#include <stdexcept>
#include <functional>
#include <iomanip>
#include <numeric>
#include <fstream>
#include <cctype>
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <set>
#include <queue>
#include <bitset>
#include <list>
#include <string>
#include <utility>
#include <map>
#include <ctime>
#include <stack> using namespace std; #define CLR(x) memset(x, 0, sizeof(x))
#define PB push_back
#define SZ(v) ((int)(v).size())
#define zero(x) (((x)>0?(x):-(x))<eps)
#define out(x) cout<<#x<<":"<<(x)<<endl
#define tst(a) cout<<#a<<endl
#define CINBEQUICKER std::ios::sync_with_stdio(false) typedef vector<int> VI;
typedef vector<string> VS;
typedef vector<double> VD;
typedef long long int64; const double eps = 1e-;
const double PI = atan(1.0)*;
const int maxint = ;
const int N = ;
const int M = ; int an[][N];
int tmp_sz;
int64 bn[][N]; int inte_dev(int x, int* an, int64* bn)
{
int all = -;
for (int i = ; i*i <= x;){
if (!(x%i)){
an[++all] = i;
bn[all] = ;
}
while (!(x%i)){
++ bn[all];
x /= i;
}
if (i == ) ++ i;
else i += ;
}
++ all;
if (x != ){
an[all] = x;
bn[all++] = ;
}
return all;
} int gao(int64 x, int a)
{
int ret = ;
while (!(x % a)){
x /= a;
++ ret;
}
return ret;
} VI vadd(VI a, VI b)
{
VI ret; ret.clear();
for (int i = ; i < tmp_sz; ++ i)
ret.PB (a[i]+b[i]);
return ret;
} class GeometricProgressions
{
public:
int count(int aa, int b, int n, int c, int d, int m){
int64 a[];
a[] = aa; a[] = b; a[] = c; a[] = d;
if (!a[] || !a[] || a[] == ){
swap (a[], a[]); swap (a[], a[]); swap (n, m);
}
if (!a[] || !a[] || a[] == ){
set<int64> tmp;
tmp.insert(a[]);
if (n > ) tmp.insert(a[]*a[]); int cnt = , sz_tmp = tmp.size();
int64 now = a[];
for (int i = ; i < m; ++ i){
if (tmp.count(now)) ++ cnt;
else tmp.insert(now);
now *= a[];
if (now > 25e16)
return m + sz_tmp - cnt;
}
return tmp.size();
} int64 all[];
for (int i = ; i < ; ++ i)
all[i] = inte_dev(a[i], an[i], bn[i]); set<int> tmp;
VI tt; tt.clear();
for (int i = ; i < ; ++ i)
for (int j = ; j < all[i]; ++ j)
if (!tmp.count(an[i][j])){
tmp.insert (an[i][j]);
tt.PB (an[i][j]);
} vector<int> v[];
for (int i = ; i < ; ++ i)
v[i].clear();
tmp_sz = tmp.size();
for (int i = ; i < ; ++ i)
for (int j = ; j < tmp_sz; ++ j)
v[i].PB (gao(a[i], tt[j])); set<VI > ans;
ans.erase(ans.begin(), ans.end());
VI now = v[];
for (int i = ; i < n; ++ i){
if (!ans.count(now)) ans.insert(now);
now = vadd(now, v[]);
}
now = v[];
for (int i = ; i < m; ++ i){
if (!ans.count(now)) ans.insert(now);
now = vadd(now, v[]);
}
return ans.size();
} // BEGIN CUT HERE
public:
//void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); }
void run_test(int Case) { if ((Case == -) || (Case == )) test_case_0();}
private:
template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
void test_case_0() { int Arg0 = ; int Arg1 = ; int Arg2 = ; int Arg3 = ; int Arg4 = ; int Arg5 = ; int Arg6 = ; verify_case(, Arg6, count(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); }
void test_case_1() { int Arg0 = ; int Arg1 = ; int Arg2 = ; int Arg3 = ; int Arg4 = ; int Arg5 = ; int Arg6 = ; verify_case(, Arg6, count(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); }
void test_case_2() { int Arg0 = ; int Arg1 = ; int Arg2 = ; int Arg3 = ; int Arg4 = ; int Arg5 = ; int Arg6 = ; verify_case(, Arg6, count(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); }
void test_case_3() { int Arg0 = ; int Arg1 = ; int Arg2 = ; int Arg3 = ; int Arg4 = ; int Arg5 = ; int Arg6 = ; verify_case(, Arg6, count(Arg0, Arg1, Arg2, Arg3, Arg4, Arg5)); } // END CUT HERE }; // BEGIN CUT HERE
int main()
{
// freopen( "a.out" , "w" , stdout );
GeometricProgressions ___test;
___test.run_test(-);
return ;
}
// END CUT HERE
SRM 500(2-1000pt)的更多相关文章
- topcoder srm 500 div1
problem1 link 如果decisions的大小为0,那么每一轮都是$N$个人.答案为0. 否则,如果答案不为0,那么概率最大的一定是一开始票数最多的人.因为这个人每一轮都在可以留下来的人群中 ...
- TC250专场
SRM 623 DIV2 1000pt 题意:给出一个最多50*50的矩阵,每个单元可能为'.'.'P'.'A','.'代表空地,你每次操作可以把一个P或者A拿到空地上,求一个最大的含有相同字符的矩形 ...
- SRM149 - SRM150(少SRM150-DIV1-LV3)
SRM 149 DIV2 1000pt 题意: 对于n个人,第i人有pi的钱.将他们分成不超过四个组,每组统一交费x,对每个人,若他拥有的钱超过x则交费,否则不交费.问最多能使这些人交多少钱. 1&l ...
- Topcoder 好题推荐
SRM SRM147 DIV1 1000pt DP SRM148 DIV1 1100pt 递归 SRM149 DIV1 1000pt math SRM150 DIV1 500pt DP SRM469 ...
- SRM 618 DIV1 500
非常棒的组合问题,看了好一会,无想法.... 有很多做法,我发现不考虑顺序的最好理解,也最好写. 结果一定是两种形式 A....A dp[n-1] A...A...A sgma(dp[j]*dp[ ...
- SRM 615 DIV1 500
TC 都615了...时间过的真快啊. 第一次做出500分,心情还是很激动的,虽然看了很久的题解,TC官网上的题解,很详细,但是英语的...我搜了搜,发现一份日语的...好吧,我还是看看英语的吧... ...
- topcoder srm 628 div2 250 500
做了一道题,对了,但是还是掉分了. 第二道题也做了,但是没有交上,不知道对错. 后来交上以后发现少判断了一个条件,改过之后就对了. 第一道题爆搜的,有点麻烦了,其实几行代码就行. 250贴代码: #i ...
- SRM 719 Div 1 250 500
250: 题目大意: 在一个N行无限大的网格图里,每经过一个格子都要付出一定的代价.同一行的每个格子代价相同. 给出起点和终点,求从起点到终点的付出的最少代价. 思路: 最优方案肯定是从起点沿竖直方向 ...
- TopCoder SRM 639 Div.2 500 AliceGameEasy
题意: 一个游戏有n轮,有A和B比赛,谁在第 i 轮得胜,就获得 i 分,给出x,y,问A得x分,B得y分有没有可能,如果有,输出A最少赢的盘数 解题思路: 首先判断n(n+1)/2 = (x+y)是 ...
随机推荐
- OpenCart 之registry功用
1. “Registry”设计模式 在OpenCart中,Registry是整个系统的信息中枢. Registry是一个单例(Singleton),在index.php起始页面中, 首先作为构造函数参 ...
- C# List
命名空间:using System.Collections; class Program {//做个比较 static void Main(string[] args) { //new对象 Cls a ...
- IIS7.5 去除 index.php web.config配置文件
论坛里有很多关于去掉index.php的教程和代码,但是悲剧的是都是自己能配置服务器,并且服务器要么是 Apache,就是IIS 6- ...没有IIS7.5下是如何配置的. 我想大家应该有很多都是用 ...
- Java循环性能随笔
for iterator做迭代循环性能最好 然后是foreach 然后是提前声明好变量的for循环 最后是每次都要计算集合size的for package test; import j ...
- table强制不换行
用iframe做了一个查询,里面有一个表格,结果当页面内容多的时候挤在了一起. 上图:
- 【POJ2886】【线段树】Who Gets the Most Candies?
Description N children are sitting in a circle to play a game. The children are numbered from 1 to N ...
- linux svn启动和关闭(转)
1,启动SVN sudo svnserve -d -r /home/data/svn/ 其中 -d 表示守护进程, -r 表示在后台执行 /home/data/svn/ 为svn的安装目录 2,关闭 ...
- ios开发之IBOutlet和IBAction的区别
IBOutlet 输出口是使用关键字IBOutlet声明的实例变量.控制器头文件中的输出口声明应如下所示: @property (nonatomic, retain) IBOutlet UIButto ...
- 用python选择及显示三级目录,可返回上层目录以及随时跳出。
# -*- coding: utf-8 -*-"""Created on Fri Jul 29 09:43:38 2016 @author: yinggang" ...
- Windows Phone 8 SQL Server CE 数据库
员工信息表 EmployeeTable.cs using System.Data.Linq.Mapping; using System.ComponentModel; namespace SQLSer ...