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)是 ...
随机推荐
- android 数字键盘制作
//布局相关<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android ...
- onContextItemSelected 用法
http://blog.csdn.net/kavensu/article/details/8045041 onCreateOptionsMenu :此方法为创建菜单方法,这个菜单就是你在点击手机men ...
- 在Iframe框架下如何跳转到登录界面
在Iframe框架下跳转到登录界面总会跳到子界面中,类似于下图 试用Respon.Redirect()不行, 用Js函数,但我跳转代码都是写在cs文件中的,用Respose.write(),js函数根 ...
- 解决js浮点数计算bug
1.加 function add(a, b) { var c, d, e; try { c = a.toString().split(".")[1].length; } catch ...
- 找出整数中第k大的数
一 问题描述: 找出 m 个整数中第 k(0<k<m+1)大的整数. 二 举例: 假设有 12 个整数:data[1, 4, -1, -4, 9, 8, 0, 3, -8, 11, 2 ...
- get方式编码问题解决方案 转载
我们的内容使用GET方式发送,就会在URL后面带上内容,在游览器发来的请求经过了游览器的URI编码,发送到服务器这边,如果是struts2会经过拦截器进行URI解码,并且使用"iso8859 ...
- CentOS6.5升级为CentOS7.0
CentOS6.5升级为CentOS7.0 CentOS6.5升级为CentOS7 升级前: [root@localhost ~]# cat /proc/version Linux version ...
- NewRowNeeded和UserAddedRow事件以及RowsAdded的区别使用
NewRowNeeded事件当 VirtualMode 属性为 true 时,将在用户定位到 DataGridView 底部的新行时发生,适合给新行建立一些默认数据和按规则应该产生的数据,但此时不推荐 ...
- java 多线程sleep和wait的区别
对于sleep()方法,我们首先要知道该方法是属于Thread类中的.而wait()方法,则是属于Object类中的. sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监 ...
- 搭建BCE本地开发环境
1. 在官网下载VirtualBox & 虚拟机 http://bce.baidu.com/doc/BAE/GUIGettingStarted.html#.E4.B8.8B.E8.BD.BD. ...