您的位置:首页 > 其它

谷歌中国算法比赛解题报告 APAC2016B

2016-11-06 06:50 666 查看
Problem A. Travel

[b]Problem B. gWheels
[/b]

[b][b]Problem C. gNumbers
[/b][/b]

[b][b]Problem
D.
 Albocede DNA
[/b][/b]



[b][b]1.
这道题,根据题目的数据,如果能早到一个点,一定不比晚到差,所以本质上还是一个DFS,就是有点麻烦,但比起APAC2015C的那道metro题要简单多了。把该定义的定义好,条理搞清晰些很容易过。
[/b][/b]



[b][b]2.
这道题,典型的先计算一遍所有 p,t的比例组合,存进map里,然后O(n2)扫描e数组,对任意两个数字,看看能不能组成的齿轮组能不能在p,t组合中找到,找到就输出YES,退出,如果全部扫描完都找不到yes,就输出no。
[/b][/b]

实现后发现大数据有些慢,看了大神的做法,也都是一样,所以这应该是最优的……

3. 博弈问题,一般来说,博弈问题的经典解法就是,如果我能找到一个获胜点,我就获胜,如果我一个都找不到,我就失败,但因为每次都两个人来回选,所以如果对方失败,我就获胜,对方获胜,我就失败。 也是就说,假设DFS会返回true,false,那么如果第k层返回false,对于第k-1层就是true……大概就是这个意思,DFS的每一层都要把下一层的结果反一下

针对这个题,同样DFS,对每个人,先查当前数字会不会输,会输就直接返回,否则,遍历这个数字的质数因子,去查生成的新数字,对方会不会输,如果对方会输,则返回赢,如果查完了所有的对方都不会输,则返回自己会输

大数据还要注意先生成一个质数库,为了方便我用set存了,注意虽然题目数据上限10的15次方,但只要找3.2*(10**7)(比平方根大就行,32000000写着方便……)以内的质数即可。暴力生成这些质数也就几秒钟的事

4.这个题很难很麻烦

大神的DP我还没来得及看,本人的思想是将ab组成pair, cd 组成pair, 然后对每个ab pair, 去找后面所有能组合的 cd pair。 具体思路如下:

先开一个数组,对每个对应位置是a的,记录以这个a开头有多少种DNA

对每个对应位置是d的,找后面所有的a,因为d可以连任意一个a,所以存下d总共可以连多少种情况,把每个a存的数量加起来

对每个对应位置是c的,找后面任意一个c,然后以这两个c为起点终点,计算有多少种c的情况(需要用到预选生成的组合库),以这个c为终点找d,记录每个cd pair有多少种

对每个对应位置是b的,把从这个b开始的后面所有c的每种情况都加过来,方便a找b时直接用(不用再加了,这是一步重要减枝)

对每个对应位置是a的,找到后面任意一个a,这两个a作为起点终点,然后在找后面的b,对每个ab pair, 找这个b 存的 cd pair 有没有对应的, 最后a记录所有从这个a开始有多少DFA

从后往前扫描:执行上面的步骤

最后,小数据可以轻松过,但是大数据要处理超时……再做一个减枝,如果ab,cdpair 任意一个数字超过250 就直接舍弃,数据量减了一半,时间上勉勉强强够

至于如何更快的解,请下大神的代码看……我没仔细研究,但基本思想看起来差不多 

最后 附上代码

#include <stdio.h>
#include <iostream>
#include <fstream>
#include <math.h>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <hash_map>
#include <hash_set>
#include <unordered_map>
#include <unordered_set>
#include <string.h>
#include <queue>
#include <list>
#include <iomanip>

using namespace std;

#define ll long long
#define uint unsigned int
#ifndef INT_MAX
#define INT_MAX 0x7fffffff
#endif

class PA
{
public:
PA(){}
int M, N, K;
struct Road
{
int id;
int from;
int to;
vector<int> timesTaken;
Road(){ id = from = to = 0; }
int getUsedTime(int currTime)
{
return timesTaken[currTime%24];
}
int getEndCity(int from_)
{
if (from_ == from) return to;
else return from;
}
};

struct City
{
int id;
vector<int> roadId;
City(){ id = 0; }
};
vector<Road> roads;
vector<City> cities;
vector<pair<int, int>> queries;

vector<vector<int>> visited;

void DFS(int start, int time, int end,int begin)
{
if (start == end)
{
visited[begin][start] = min(visited[begin][start], time);
return;
}

if (visited[begin][start] <= time) return;

visited[begin][start] = time;
for (int i = 0; i < cities[start].roadId.size(); i++)
{
int roadid = cities[start].roadId[i];
int to = roads[roadid].getEndCity(start);
DFS(to, roads[roadid].getUsedTime(time) + time, end,begin);
}
}

void SingleProcess(ofstream& fout)
{

visited.clear();
visited.resize(24,vector<int>(N, INT_MAX));
for (int i = 0; i < 24; i++)
{
DFS(0, i, INT_MAX,i);
}

for (int i = 0; i < queries.size(); i++)
{
if (visited[queries[i].second%24][queries[i].first] == INT_MAX)
{
fout << -1 << " ";
}
else fout << visited[queries[i].second % 24][queries[i].first] - (queries[i].second % 24) << " ";
}
}

void run()
{
FILE* fp = freopen("in.txt", "r", stdin);
ofstream fout("out.txt");
int Cases = 0;
scanf("%d", &Cases);
for (int time = 0; time < Cases; time++)
{
cin >> N >> M >> K;
cities.clear();
cities.resize(N);
roads.clear();
roads.resize(M);
queries.clear();
queries.resize(K);
for (int i = 0; i < N; i++)
{
cities[i].id = i;
}
for (int i = 0; i < M; i++)
{
roads[i].id = i;
cin >> roads[i].from >> roads[i].to;
roads[i].from--;
roads[i].to--;
cities[roads[i].from].roadId.push_back(i);
cities[roads[i].to].roadId.push_back(i);
roads[i].timesTaken.resize(24, 0);
for (int j = 0; j < 24; j++)
{
cin >> roads[i].timesTaken[j];
}
}
for (int i = 0; i < K; i++)
{
cin >> queries[i].first >> queries[i].second;
queries[i].first--;
queries[i].second;
}

fout << "Case #" << (time + 1) << ": ";
SingleProcess(fout);
fout << endl;
std::cout << time << endl;
}
fclose(fp);
fout.close();
}
};

class PB
{
public:
PB(){}
int NP, NE,NT;
int M;

ll GCD(ll v1, ll v2)
{
while (v1)
{
ll temp = v1;
v1 = v2%v1;
v2 = temp;
}
return v2;
}
set<pair<ll,ll>> eeset, ptset;
vector<ll> pvec, evec, tvec;
vector<pair<ll, ll>> queries;

void SingleProcess(ofstream& fout)
{
ptset.clear();

for (int i = 0; i < pvec.size(); i++)
{
for (int j = 0; j < tvec.size(); j++)
{
int g = GCD(pvec[i], tvec[j]);
ll t1 = pvec[i] / g;
ll t2 = tvec[j] / g;
ptset.insert(make_pair(t1,t2));
}
}

for (int i = 0; i < queries.size(); i++)
{
bool findone = false;
for (int e1 = 0; e1 < NE;e1++)
{
for (int e2 = 0; e2 < NE;e2++)
{
if (e1 == e2) continue;

ll t1 = evec[e1]*queries[i].first;
ll t2 = evec[e2]*queries[i].second;
ll g = GCD(t1, t2);
t1 /= g;
t2 /= g;
if (ptset.find(make_pair(t1,t2))!=ptset.end())
{
fout << endl << "Yes";
findone = true;
break;
}
}
if (findone) break;

}
if (!findone)
{
fout << endl << "No";
}
}

}

void run()
{
FILE* fp = freopen("in.txt", "r", stdin);
ofstream fout("out.txt");
int Cases = 0;
scanf("%d", &Cases);
for (int time = 0; time < Cases; time++)
{
cin >> NP >> NE >> NT;
pvec.resize(NP);
evec.resize(NE);
tvec.resize(NT);
for (int i = 0; i < NP; i++)
{
cin >> pvec[i];
}
for (int i = 0; i < NE; i++)
{
cin >> evec[i];
}
for (int i = 0; i < NT; i++)
{
cin >> tvec[i];
}
cin >> M;
queries.resize(M);
for (int i = 0; i < M; i++)
{
cin >> queries[i].first >> queries[i].second;
}

fout << "Case #" << (time + 1) << ": ";
SingleProcess(fout);
fout << endl;
std::cout << time << endl;
}
fclose(fp);
fout.close();
}
};

class PC
{
public:
PC(){}
ll N;
vector<ll> primes;
set<ll> primeSet;
map<ll, bool> winMap;
void predefine()
{
ll UPPER = 32000000;
for (int i = 2; i < UPPER; i++)
{
bool findone = false;
for (int j = 0; j < primes.size(); j++)
{
if (primes[j] * primes[j]>i) break;
if (i%primes[j] == 0)
{
findone = true;
break;
}
}
if (!findone)
{
primes.push_back(i);
primeSet.insert(i);
}
}
}

bool isGNumber(ll num)
{
ll ss = 0;
while (num > 0)
{
ss += num % 10;
num = num / 10;
}

if (ss == 1) return true;

for (int i = 0; i < primes.size(); i++)
{
if (primes[i]>ss) return false;
if (primes[i] == ss) return true;
}
return false;
}

bool DFS(ll num)
{
if (winMap.find(num) != winMap.end()) return winMap[num];
if (isGNumber(num)) return false;
if (primeSet.find(num) != primeSet.end()) return true;

ll upper = sqrt(num) + 1;
ll temp = num;
for (int i = 0; i < primes.size(); i++)
{
if (primes[i]>=upper) break;
if (temp%primes[i] == 0)
{
ll t1 = primes[i];
while (temp%t1 == 0) t1 *= primes[i];
t1 /= primes[i];
temp /= t1;
if (DFS(num/t1) == false)
{
winMap[num] = true;
return true;
}
}
}
//留下来的也是质数,不是1就测试num/temp
if (temp > 1)
{
if (DFS(num / temp) == false)
{
winMap[num] = true;
return true;
}
}
winMap[num] = false;
return false;
}

void SingleProcess(ofstream& fout)
{
//winMap.clear();
if (DFS(N))
{
fout << "Laurence";
}
else
{
fout << "Seymour";
}
}

void run()
{
FILE* fp = freopen("in.txt", "r", stdin);
ofstream fout("out.txt");
int Cases = 0;
scanf("%d", &Cases);
predefine();
for (int time = 0; time < Cases; time++)
{
cin>>N;

fout << "Case #" << (time + 1) << ": ";
SingleProcess(fout);
fout << endl;
std::cout << time << endl;
}
fclose(fp);
fout.close();
}
};

class PD
{
public:
PD(){}
string S;
ll MODE = 1e9 + 7;
vector<vector<ll>> C;
void preDefine()
{
C.resize(501, vector<ll>(501, 0));
for (int i = 0; i < 501; i++)
{
for (int j = 0; j <= i; j++)
{
if (j == 0) C[j][i] = 1;
else if (i == j) C[j][i] = 1;
else C[j][i] = C[j - 1][i - 1] + C[j][i-1];
C[j][i] %= MODE;
}
}
}
struct SingleWord
{
char word;
ll num;
//map<pair<ll, ll>, ll> pairs;
vector<vector<ll>> pairs;
SingleWord(){ word = '0'; num = 0;}
};
vector<SingleWord> wordvec;

void SingleProcess(ofstream& fout)
{
wordvec.clear();
wordvec.resize(S.length());
for (int i = S.length()-1; i>=0; i--)
{
if (S[i] == 'd')
{
wordvec[i].word = 'd';
wordvec[i].num = 1;
for (int j = i + 1; j < S.length(); j++)
{
if (S[j] == 'a') wordvec[i].num += wordvec[j].num;
}
wordvec[i].num %= MODE;
}
else if (S[i] == 'c')
{
wordvec[i].pairs.clear();
wordvec[i].pairs.resize(251, vector<ll>(251, 0));
int ct = 0;
int dt = 0;
for (int j = i + 1; j < S.length(); j++)
{
if (S[j] == 'c') ct++;
else if (S[j] == 'd')
{
//以j为起点'd';
dt = 0;
//先算以j为终点的cd,pair
for (int kc = min(ct,249); kc >= 0; kc--)
{
ll t = C[kc][ct] * wordvec[j].num%MODE;
wordvec[i].pairs[kc+1][1] += t;
}

//再算以j后面的k为终点的cd,pair
for (int k = j + 1; k < S.length(); k++)
{
if (S[k] == 'd') //以这个'd'为终点
{
for (int kc = min(ct,249); kc >= 0; kc--)
{
for (int kd = min(dt,248); kd >= 0; kd--)
{
ll t = C[kc][ct] * C[kd][dt] % MODE *wordvec[k].num%MODE;
wordvec[i].pairs[kc + 1][kd+2] += t;
}
}
dt++;
}
}
}
}
}
else if (S[i] == 'b')
{
wordvec[i].pairs.clear();
wordvec[i].pairs.resize(251, vector<ll>(251, 0));
//每个b点把后面的cdpair 综合起来,这样a过来查到b就不用往后查了
for (int j = i + 1; j < S.length(); j++)
{
if (S[j] == 'c')
{
for (int t1 = 0; t1 < 251;t1++)
{
for (int t2 = 0; t2 < 251; t2++)
{
wordvec[i].pairs[t1][t2] += wordvec[j].pairs[t1][t2];
wordvec[i].pairs[t1][t2] %= MODE;
}
}
}
}

}
else if (S[i] == 'a')
{
//查找所有以这个a为起点的abpair;
int ta = 0;
for (int j = i + 1; j < S.length(); j++)
{
if (S[j] == 'a')
{
ta++;
}
else if (S[j] == 'b')
{
//以这个b为起点
//先算以这个b为终点
int tb = 0;
ll tot = 0;
for (int ka = min(ta,249); ka >= 0; ka--)
{
//找后面所有能匹配的cdpair
tot += wordvec[j].pairs[ka + 1][1] * C[ka][ta] % MODE;
}
wordvec[i].num += tot;

//再算以这个b为起点,以后面的b为终点
tb = 0;
for (int k = j + 1; k < S.length(); k++)
{
if (S[k] == 'b')
{
tot = 0;
for (int ka = min(ta,249); ka >= 0; ka--)
{
for (int kb = min(tb,248); kb >= 0; kb--)
{
tot += C[kb][tb] * C[ka][ta] % MODE*wordvec[k].pairs[ka+1][kb+2]%MODE;
}
}
wordvec[i].num += tot;
wordvec[i].num %= MODE;
tb++;
}
}
}
}
}

}

ll total = 0;
for (int i = 0; i < S.length(); i++)
{
if (S[i] == 'a')
{
total += wordvec[i].num;
total %= MODE;
}
}
fout << total;
return;
}

void run()
{
FILE* fp = freopen("in.txt", "r", stdin);
ofstream fout("out.txt");
int Cases = 0;
scanf("%d", &Cases);
preDefine();
for (int time = 0; time < Cases; time++)
{
char ch[1024];
cin >> ch;
S = ch;

fout << "Case #" << (time + 1) << ": ";
SingleProcess(fout);
fout << endl;
std::cout << time << endl;
}
fclose(fp);
fout.close();
}
};

int main()
{
//PA p;
//PB p;
//PC p;
PD p;
p.run();

return 0;
}


8649
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: