1 / 17

7.2,7.6结题报告 --陈静

7.2,7.6结题报告 --陈静. 7.2 排名系统. 题目描述 :   osu!是一款ytaaa最喜欢的音乐游戏,但是最近ytaaa的排名一直没有上升,所以ytaaa打算研究一下osu的排名系统。 osu!的排名是以pp来排序的,pp越高排名越靠前。现在ytaaa弄到了osu的排名数据,出于见不得人的目的,ytaaa想知道pp值为k的用户的资料,但是即使弄到了数据,查询也需要耗费大量的时间,所以ytaaa希望你能帮助他写一段代码来快速的给出ytaaa想要的信息。. 7.2 排名系统. 解题思路: 1.根据pp值是按从高到低排好序

hart
Download Presentation

7.2,7.6结题报告 --陈静

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 7.2,7.6结题报告 --陈静

  2. 7.2 排名系统 题目描述:   osu!是一款ytaaa最喜欢的音乐游戏,但是最近ytaaa的排名一直没有上升,所以ytaaa打算研究一下osu的排名系统。 osu!的排名是以pp来排序的,pp越高排名越靠前。现在ytaaa弄到了osu的排名数据,出于见不得人的目的,ytaaa想知道pp值为k的用户的资料,但是即使弄到了数据,查询也需要耗费大量的时间,所以ytaaa希望你能帮助他写一段代码来快速的给出ytaaa想要的信息。

  3. 7.2 排名系统 解题思路: 1.根据pp值是按从高到低排好序 2.我们要找pp为k的数据的位置,就可以输出对应的资料 3.由于数据很大,1<=n<=100000,1<=m<=10000,枚举的复杂度是O(m*n),会超时,所以我们需要用二分法,复杂度是O(m*log(2)n)。

  4. 7.2 排名系统 解题思路: 二分法上次课已经讲过,这里不再赘述  二分法主要代码  int bidsch(int k){ int l=0,r=n-1; if(a[l].pp==k)return l; if(a[r].pp==k)return r; int mid; for(;;){ mid=(l+r)/2; if(a[mid].pp==k)return mid; else if(a[mid].pp>k)l=mid; else r=mid;}}

  5. 7.2 排名系统 主要代码: struct data{ char s[15]; int pp; }a[100005]; int n; int cmp(data x,data y){ return x.pp>y.pp;} int main(){ scanf("%d",&n); int i; for(i=0;i<n;i++) scanf("%s%d",a[i].s,&a[i].pp); sort(a,a+n,cmp);//快排排序 int m; scanf("%d",&m); while(m--){ int k; scanf("%d",&k); printf("%s\n",a[bidsch(k)].s); } return 0;}  

  6. 7.6 永真判断 题目描述:   这道题的目的是判断一串逻辑表达式是否为永真式(即不论逻辑变量如何取值,其结果永远为真)。为了减小计算难度,这串式子中只会出现a,b,c,d,e,5个逻辑变量(体贴的老师)。共涉及4个操作,分别是K,A,N,E。Kab指a&&b,Aab指a||b,Na指!a,E指a==b(相等取真),例如EKAabNaEcd(E(K(Aab)(Na))(Ecd))是一个合法的表达串,AaNa为永真式,因为不论a的取值是真是假,AaNa恒为真,而AaNb就不是一个永真式。为了增加难度,一个合法串的长度可能到达100。

  7. 7.6 永真判断 首先了解一个前序表达式的概念 前序表达式就是不含括号的算术表达式,而且它是将运算符写在前面,操作数写在后面的表达式,也称为“波兰式”。例如,- 1 + 2 3,它等价于1-(2+3)。 题目的表达式其实也可以看做前序表达式,只是它的运算是逻辑运算而不是算术运算

  8. 7.6 永真判断 解题思路: 所以这是一个对前序表达式的运算问题 对于一个前序表达式的求值而言,首先要从右至左扫描表达式,从右边第一个字符开始判断,如果当前字符是数字则一直到数字串的末尾再记录下来,如果是运算符,则将右边离得最近的两个“数字串”作相应的运算,以此作为一个新的“数字串”并记录下来。一直扫描到表达式的最左端时,最后运算的值也就是表达式的值。。

  9. 7.6 永真判断 解题思路: 对于一个前序表达式的求值而言,首先要从右至左扫描表达式,从右边第一个字符开始判断,如果当前字符是数字则一直到数字串的末尾再记录下来,如果是运算符,则根据运算符的的运算变量的个数将右边离得最近的一个或两个“数字串”作相应的运算,以此作为一个新的“数字串”并记录下来。一直扫描到表达式的最左端时,最后运算的值也就是表达式的值。

  10. 7.6 永真判断 解题思路: 例如,前序表达式“- 1 + 2 3“的求值,扫描到3时,记录下这个数字串,扫描到2时,记录下这个数字串,当扫描到+时,将+右移做相邻两数字串的运算符,记为2+3,结果为5,记录下这个新数字串,并继续向左扫描,扫描到1时,记录下这个数字串,扫描到-时,将-右移做相邻两数字串的运算符,记为1-5,结果为-4,所以表达式的值为-4。

  11. 7.6 永真判断 解题思路: 如果你理解了上面的运算,那么对于这题的运算你应该也明白了! 那我们就举个这题的例子EKAabNaEcd我们知道它的运算过程是(E(K(Aab)(Na))(Ecd)) 同理根据上面的方法,先从右开始扫描,碰到a,b,c,d,e的就跳过,直到遇到运算符即K,A,N,E

  12. 7.6 永真判断 解题思路: 所以先运算Ecd,然后把运算后的结果s1可以存到新的数组里面,继续扫描,遇到 N,那么就运算Na,同时保存结果s2,再运算Aab,结果为s3,继续像左扫描,遇到K,此时拿紧邻的右边的2个数s2,s3来运算,得到s4,最后是遇到E,此时再判断s4和s1是否相等,最后得到s5,此时扫描结束,那么s5就是最后的答案

  13. 7.6 永真判断 解题思路: 还有一个问题是a,b,c,d,e的值不确定,所以共有2的5次方即32种可能,所以我们每一种情况都要判断表达式的 真假,如果32种情况下,表达式都为真,那么就是永真式

  14. 7.6 永真判断 解题思路: 前面的解法可以有很多实现方法,可以用栈 参考代码是用函数递归的方式实现的

  15. 7.6 永真判断 示例代码: #include<stdio.h> har a[10000]; int k; int f[10]; bool judge(void){//递归函数 k++; if(a[k]=='K')return judge()&judge(); if(a[k]=='A')return judge()|judge(); if(a[k]=='N')return !judge(); if(a[k]=='E')return judge()==judge(); return f[a[k]-'a']; }

  16. 7.6 永真判断 示例代码: int main(){ scanf("%s",a); bool mark=true; for(f[0]=0;f[0]<=1;f[0]++) for(f[1]=0;f[1]<=1;f[1]++) for(f[2]=0;f[2]<=1;f[2]++) for(f[3]=0;f[3]<=1;f[3]++) for(f[4]=0;f[4]<=1;f[4]++){ k=-1; if(!judge())mark=false; } if(mark)printf("Yes\n");//全都为真 else printf("No\n"); return 0; }

  17. THANK YOU

More Related