@tankle
2015-09-13T13:37:22.000000Z
字数 10088
阅读 2670
面试
时间限制:5000ms
单点时限:1000ms
内存限制:256MB
描述
师徒系统普遍存在于各类网络游戏中,对于游戏促进新手留存具有重要意义,现在采集到如下信息:
| 好友个数 | 聊天次数 | 是否是好师父 |
|---|---|---|
| 1 | 3 | 1 |
| 2 | 1 | 2 |
希望你用naïve bayes算法基于“好友个数”和“聊天次数”推算某玩家是好师父的概率,以方便产品优化匹配规则。
输入
输入数据由多行构成,每行中的数据用“\t”分隔。第1行是1~3个用“\t”分隔的数字,表示输出第几个问题的答案,第2行是属性名称,包括fchatnum,cchatnum和remark三个属性,分别代表好友个数、聊天次数和是否是好师父。从第3行开始为训练数据,含义与第2行的属性名称相对应。好友个数和聊天次数取值都是1~10的整数,是否是好师父取值是1~2的整数,其中2表示好师父。
输出
根据第1行输入数据指定的编号输出以下3个小题的答案,多个小题答案使用换行“\n”分割。
第1题:输出好师父的先验概率。
第2题:输出好师父群体中好友个数取值的概率分布,依次对应1~10的概率取值,零值也要输出,中间用逗号分隔。
第3题:输出给定fchatnum=9,cchatnum=9的玩家是好师父的概率。
输出结果统一四舍五入保留小数点后3位。
完整样例输入下载
总计1000条数据,请在这里下载。
样例输入
1 2 3fchatnum cchatnum remark1 2 13 3 11 1 16 9 23 7 24 6 24 2 23 8 21 1 18 4 2……样例输出0.3200.034,0.091,0.075,0.144,0.100,0.106,0.119,0.134,0.100,0.0970.691
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <vector>#include <climits>#include <cmath>#include <map>using namespace std;void count(vector<int>& fchat, vector<int>& remark, vector<float>& num,int target){for(int i=0; i<remark.size(); i++){if(remark[i] == target){num[fchat[i]]++;}}}void output(int n, float goodrate, vector<float>& num, float threeres){switch (n) {case 1:printf("%.3f\n", goodrate);break;case 2:for(int i=1; i<num.size(); i++){if(i == num.size()-1)printf("%.3f\n", num[i]);elseprintf("%.3f,", num[i]);}break;case 3:printf("%.3f\n", threeres);break;}}int main(){vector<int> fchat;vector<int> cchat;vector<int> remark;int a, b,c;int one, two, three;scanf("%d %d %d", &one, &two, &three);map<string, vector<int>> str2vec;string s1, s2, s3;cin>>s1>>s2>>s3;while(cin>>a>>b>>c){// if(a == -1)// break;str2vec[s1].push_back(a);str2vec[s2].push_back(b);str2vec[s3].push_back(c);}fchat = str2vec["fchatnum"];cchat = str2vec["cchatnum"];remark = str2vec["remark"];int good = 0;for(int i=0; i<remark.size(); i++)if(remark[i] == 2)good++;float goodrate = good * 1.0 / remark.size();vector<float> num(11, 0);count(fchat, remark, num, 2);//好师傅的前提下,好友个数的概率分布for(int i=1; i<num.size(); i++){num[i] = num[i] * 1.0 / good;}vector<float> cnum(11, 0);count(cchat, remark, cnum, 2);for(int i=1; i<cnum.size(); i++) {cnum[i] = cnum[i] * 1.0 / good;}vector<float> num1(11,0);count(fchat, remark, num1, 1);vector<float> cnum1(11, 0);count(cchat, remark, cnum1, 1);float goodres = goodrate * num[9] * cnum[9];int notgood = remark.size() - good;float notres = (1 - goodrate) * num1[9] * cnum1[9] / (notgood * notgood);//NB公式float threeres = goodres / (goodres + notres);output(one, goodrate, num, threeres);output(two, goodrate, num, threeres);output(three, goodrate, num, threeres);return 0;}
时间限制:25000ms
单点时限:5000ms
内存限制:256MB
描述
理查德•巴图博士通过对游戏中玩家固定的行为模式进行观察,于1996年提出了巴图模型,尝试把玩家的不同行为模式进行分类。他将游戏玩家分成了成就型、探索型、社交型和杀手型。该分类方式本质上从玩家在游戏中的需求出发,根据具体的行为表现对其进行分类。推断玩家所属类型,对于游戏用户研究,精准营销投放都有非常重要的意义,因此对不同玩家进行分类是一项重要研究工作。为了实现分类模型,通过收集玩家在游戏中的不同行为数据并进行归一化,可以得到玩家的特征向量以及已知类型玩家的标签,如:
| 副本参与次数 | 竞技场参与次数 | 任务完成次数 | 登陆频率 | 充值额度 | 玩家类型 |
|---|---|---|---|---|---|
| 0.8 | 0.5 | 0.6 | 0.9 | 0.2 | A |
| 0.4 | 0.8 | 0.1 | 0.2 | 0.1 | B |
| 0.9 | 0.1 | 0.5 | 0.6 | 0.9 | C |
| 0.5 | 0.2 | 0.1 | 0.3 | 0.0 | D |
(其中前五列数字为玩家的特征向量,最后一列字母是玩家类型,有A、B、C、D四种取值)
分类问题有多种解决算法,其中K最近邻(k-Nearest Neighbor,KNN)分类算法是最简单的机器学习算法之一,其思想是:如果一个样本在特征空间中的k个最相似的样本中的大多数属于某一个类别,则该样本也属于这个类别。请用该方法实现游戏玩家分类,距离度量函数采用欧氏距离。
输入
每个输入数据包含一组训练数据和一组测试数据。
第一行第一个数为KNN算法的k(k<=10000)值,第二个数为特征向量的长度L(L<=100),第三个数M(M>k, M<=10000)为训练数据行数,第四个数N(N<=10000)为测试数据行数。之后是M行训练数据和N行测试数据。每行中数据使用空格分隔。
输出
对于每行测试数据,输出该玩家的类型,例如“A”。如果前K个相似类型中,出现数量最多的类型有重复,则一起输出,以ABCD升序排列,例如“AC”。
样例输入
3 5 16 20.19 0.04 0.06 0.22 0.11 A0.28 0.42 0.38 0.39 0.44 B0.71 0.61 0.54 0.52 0.54 C0.98 0.82 0.92 0.98 0.97 D0.05 0.03 0.15 0.01 0.11 A0.33 0.29 0.33 0.47 0.27 B0.72 0.52 0.61 0.71 0.68 C0.78 0.86 0.91 1.0 0.76 D0.01 0.17 0.14 0.15 0.2 A0.44 0.36 0.32 0.32 0.35 B0.67 0.65 0.57 0.58 0.52 C0.87 0.92 0.8 0.83 0.77 D0.01 0.11 0.14 0.12 0.07 A0.33 0.43 0.43 0.45 0.38 B0.57 0.54 0.75 0.7 0.64 C0.9 0.94 0.83 0.96 0.77 D0.29 0.29 0.42 0.36 0.270.56 0.67 0.71 0.66 0.7样例输出BC
#include <iostream>#include <vector>#include <math.h>#include <map>#include <algorithm>using namespace std;struct sample {char label;double distance;};bool cmp1(sample a, sample b){if (a.distance == b.distance)return a.label < b.label;return a.distance < b.distance;}bool cmp2(pair<char, int> a, pair<char, int> b){if (a.second == b.second)return a.first < b.first;return a.second > b.second;}void readTrainData(vector<vector<double> > &trainData, vector<char> &trainLabel, int L, int M){for (int i = 0; i < M; ++i) {// 读入训练数据特征vector<double> lineData;double tmpData;for (int j = 0; j < L; ++j) {cin >> tmpData;lineData.push_back(tmpData);}trainData.push_back(lineData);// 读入训练数据类别char label;cin >> label;trainLabel.push_back(label);}}void readTestData(vector<vector<double> > &testData, int L, int N){for (int i = 0; i < N; ++i) {vector<double> lineData;double tmpData;for (int j = 0; j < L; ++j) {cin >> tmpData;lineData.push_back(tmpData);}testData.push_back(lineData);}}double calcDistance(vector<double> data1, vector<double> data2){int length = data1.size();double distance = 0.0;for (int i = 0; i < length; ++i)distance += pow(data1[i] - data2[i], 2);return sqrt(distance);}void KNN(vector<vector<double> > trainData, vector<vector<double> > testData,vector<char> trainLabel, vector<char> &testLabel, int k, int L, int M, int N){for (int i = 0; i < N; ++i) {// 计算每一个测试样本与所有训练样本的距离,并排序。vector<sample> distances;for (int j = 0; j < M; ++j) {sample tmpDistance;tmpDistance.distance = calcDistance(testData[i], trainData[j]);tmpDistance.label = trainLabel[j];distances.push_back(tmpDistance);}sort(distances.begin(), distances.end(), cmp1);//for (int j = 0; j < M; ++j)// cout << distances[j].distance << " " << distances[j].label << endl;//cout << "-------" << endl;// 选择前k个样本的距离,投票选择类别。map<char, int> labelMap;for (int j = 0; j < k; ++j) {if (!labelMap[distances[j].label])labelMap[distances[j].label] = 0;labelMap[distances[j].label] += 1;}//for (map<char, int>::iterator it = labelMap.begin(); it != labelMap.end(); ++it)// cout << (*it).first << " " << (*it).second << endl;//cout << "--------" << endl;for (int j = k; j < M; ++j) {if (distances[j].distance == distances[k-1].distance) {if (!labelMap[distances[j].label])labelMap[distances[j].label] = 0;labelMap[distances[j].label] += 1;}}//for (map<char, int>::iterator it = labelMap.begin(); it != labelMap.end(); ++it)// cout << (*it).first << " " << (*it).second << endl;//cout << "--------" << endl;vector<pair<char, int> > labelVec;for (map<char, int>::iterator it = labelMap.begin(); it != labelMap.end(); ++it)labelVec.push_back(make_pair((*it).first, (*it).second));sort(labelVec.begin(), labelVec.end(), cmp2);//for (int j = 0; j < labelVec.size(); ++j)// cout << labelVec[j].first << " " << labelVec[j].second << endl;//cout << "--------" << endl;string res = "";for (int j = 0; j < labelVec.size(); ++j) {res += labelVec[j].first;if (j + 1 >= labelVec.size() || labelVec[j].second != labelVec[j+1].second)break;}if (i == 0)cout << res;elsecout << "\n" << res;}}int main(){int k, L, M, N;cin >> k >> L >> M >> N;vector<vector<double> > trainData;vector<vector<double> > testData;vector<char> trainLabel;vector<char> testLabel;readTrainData(trainData, trainLabel, L, M);readTestData(testData, L, N);KNN(trainData, testData, trainLabel, testLabel, k, L, M, N);return 0;}
时间限制:5000ms
单点时限:1000ms
内存限制:256MB
描述
作为一名游戏行业的数据分析师,每天都会面对大量的游戏数据,对游戏数据进行统计分析必不可少。有效地使用SQL进行数据统计,可以帮助你在工作中获得事半功倍的效果。
请阅读以下SQL,理解SQL的语法含义,根据输入数据,编码输出该SQL的执行结果。
SELECTctype,COUNT(DISTINCT pid) AS pcnt,SUM(cash) AS cashFROM(SELECTplayer_channel.pid AS pid,player_channel.ctype AS ctype,prepaid.cash AS cashFROM(SELECTplayers.pid AS pid,IF(channels.ctype IS NULL, -1, channels.ctype) AS ctypeFROMchannelsRIGHT OUTER JOINplayersONchannels.cid=players.cid) player_channelLEFT OUTER JOINprepaidONplayer_channel.pid=prepaid.pid) channel_prepaidGROUP BYctypeORDER BYcash DESC, ctype ASC;
输入
包含SQL语句中涉及的表数据,每个表的相关数据由以下内容组成:
第一行包含两个数据:tname(字符串类型,长度不超过10,保证为有效单词)和m(0<=m<=1000),用空格分隔。其中tname表示该表的名字,m表示该表有m行数据;
第二行为3个字符串(保证为有效单词,长度不超过10),用空格分隔,表示该表的字段名,每个表的字段顺序如下,
channels 表包含字段:cid,name,ctype,其中cid为主键
players 表包含字段:pid,name,cid,其中pid为主键
prepaids 表包含字段:id,pid,cash,其中id为主键
接下来m行,每行3个用空格分隔的数据,仅name字段的数据为字符串类型(长度不超过10,保证为有效单词),其他均为非负整型。
输出
根据输入数据,输出SQL的执行结果。
样例输入channels 3cid name ctype1 netease 02 iplay 03 appstore 1players 7pid name cid1 Smith 12 Carter 23 Linda 24 Bush 35 Adam 46 Gates 57 Hill 1prepaids 8id pid cash1 3 10002 4 30003 1 20004 6 10005 7 20006 2 20007 5 60008 3 2000样例输出0 4 9000-1 2 70001 1 3000
题解
import rewhile True:try:data = {"channels": {"cid":[], "name":[], "ctype":[]},"players": {"pid":[], "name":[], "cid":[]},"prepaids": {"id":[], "pid":[], "cash":[]}}for i in range(3):name, num = input().split()num = int(num)a, b, c = input().split()for j in range(num):n1, n2, n3 = input().split()data[name][a].append(n1)data[name][b].append(n2)data[name][c].append(n3)player_channels = {"pid":[], "ctype":[], "cash":[]}channels = data["channels"]players = data["players"]prepaids = data["prepaids"]for i in range(len(players["pid"])):pid = players["pid"][i]player_channels["pid"].append(pid)cid = players["cid"][i]if cid not in channels["cid"]:type = "-1"else:type = channels["ctype"][channels["cid"].index(cid)]player_channels["ctype"].append(type)flag = 0for idx in range(len(prepaids["pid"])):pidd = prepaids["pid"][idx]if pidd == pid:if flag == 0:player_channels["cash"].append(prepaids["cash"][idx])flag = 1else:player_channels["pid"].append(pid)player_channels["ctype"].append(type)player_channels["cash"].append(prepaids["cash"][idx])# print(player_channels)results = {}ctypes = player_channels["ctype"]for i in range(len(ctypes)):ctype = ctypes[i]if ctype not in results:results[ctype] = {"pid":set(),"cash":0}results[ctype]["pid"].add(player_channels["pid"][i])results[ctype]["cash"] += int(player_channels["cash"][i])# print(results)res = []for key, value in results.items():res.append((int(key), len(value["pid"]), value["cash"]))from operator import itemgetter, attrgetterres = sorted(res,key=itemgetter(2, 0),reverse=True)for item in res:print(item[0],item[1],item[2])except EOFError:break
时间限制:5000ms
单点时限:1000ms
内存限制:256MB
描述
虚拟游戏世界里面有很多实体,实体可能由很多子实体或者子属性构成。由于实体之间可能有非常之多的嵌套,查询某个实体或者属性属于第几层嵌套,以便将来对虚拟世界的修改和展示是一项待解决的问题,作为未来的虚拟世界分析员,你能用程序解决这个问题吗?
输入
输入数据可能由多组数据构成,每组数据由两行构成:
第一行是对虚拟世界的描述,实体或者属性由英文字母或者数字构成,子实体和子属性紧接着父实体嵌套在{}中,兄弟实体或者属性用“,”分隔。
第二行是要查询的属性或者实体,有且仅有一个。
注意数据输入可能很大。
输出
输出为查询的实体或者属性的层数;如果属性不存在,输出-1;如果有多个结果满足查询,请从小到大输出所有去重之后的结果,用”,”分隔
样例输入Fruit{apple{shape,color},orange{taste,price}}FruitFruit{apple{shape,color},orange{taste,price}}orangeFruit{apple{shape,color},orange{color,price},color}color样例输出122,3
题解
import rewhile True:try:data = raw_input()sstr = raw_input()sstr = sstr.strip()res = re.findall(sstr, data)if len(res) == 0:print(-1)else:index = 1#将单词之间插入空格,方便后面的切分data = data.replace("{", " { ").replace("}", " } ").replace(",", " , ")data = data.split(" ")ress = set()level = 1for w in data:w = w.strip()if w == '{':level += 1elif w == '}':level -= 1elif w == sstr:ress.add(level)ress = list(ress)sorted(ress)out = ",".join([str(i) for i in ress ])print(out)except EOFError:break