码迷,mamicode.com
首页 > 其他好文 > 详细

清北学堂Day2

时间:2017-10-02 20:21:00      阅读:192      评论:0      收藏:0      [点我收藏+]

标签:sdn   print   lin   ext   log   16px   ref   unix   cstring   

Part1:模拟题

今天的题有点难啊,只得了第一题的60分。不过让人欣慰的是,大多数人都只得了第一题的六十分。

技术分享

60分做法:z老师说的是打表或者暴力就能拿到。暴力应该是要做一点优化。我是枚举了a和(a*b)然后判断b是否是因数(即在数组a中)。刚开始我想用set储存因数,因为可以直接用s.count()来判断是不是因数。但是有别的问题。就是他只能访问到第一个或最后一个数。所以要更新a的话只能删掉第一个数。这样的话后面再判断是否为因数时会受影响。比较气的是我都写完了才发现这个问题,然后又删掉老老实实的用数组写了一遍,耽误了不少时间。(不过后两题也不会写)

我的代码:

技术分享
 1 #include <iostream>
 2 #include <cmath>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 using namespace std;
 8 int n,ans,ge;
 9 int a[10101];
10 bool is_prime(int x)  //判断质数 
11 {
12     if(x==2) return true;
13     for(int i=2;i<=sqrt(x);i++)
14         if(x%i==0) return false;
15     return true;
16 }
17 void find(int x) //找因数 
18 {
19     for(int i=1;i<=x;i++)
20         if(x%i==0) a[++ge]=i;
21 }
22 
23 int main()
24 {
25     
26     freopen("a.in","r",stdin);
27     freopen("a.out","w",stdout);
28     
29     scanf("%d",&n);
30     ans=1;
31     for(int i=2;i<=n;i++)
32     {
33         if(is_prime(i)) {ans+=3;continue;}  //即(1,1) (1,i) (i,1)三种情况 
34         memset(a,0,sizeof(a));
35         ge=0;find(i);
36         ans+=2*ge-1;  //即(1,1) (1,a[1])(a[1],1) (1,a[2])(a[2],1) ... (1,a[ge])(a[ge],1)
37         for(int j=2;j<ge;j++)//枚举a 
38         {
39             for(int k=j+1;k<=ge;k++) //枚举(a*b) 
40             {
41                 if(a[k]%a[j]!=0) continue; /*除不尽的就不要再考虑了。这点刚开始没想到,错了好几次*/ 
42                 int c=a[k]/a[j];   
43                 if(i%c==0) ans++;//如果b也在a数组中,则符合条件
44             }
45         }
46     }
47     printf("%d",ans);
48     return 0;
49 }
a60

100分做法:题意实际上就是枚举a,b找有多少数是(a*b)的倍数(将倍数设为c),即枚举a*b*c。可假定a<b<c,那么将枚举出来的数*6即为最终答案【(1,2,3)(1,3,2)(2,1,3)...共六种排列方式,答案一样】(此处埋下一个BUG)

因为a<b<c,所以a的循环只需要到技术分享,即(a=1;a*a*a<=n;a++)就行了。

同理,b*b<=n/a(a*b*c<n  b*c<n/a;因为b<c,所以b*b<n/a)

然而仅仅这样做是不对的。因为我们没有考虑其中有2个或3个数相等的情况。下面要再开个循环考虑一下。

标程:

技术分享
 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 long long n;
 8 
 9 #ifdef unix
10 #define LL "%lld"
11 #else
12 #define LL "%I64d"
13 #endif
14 
15 int main()
16 {
17     freopen("a.in","r",stdin);
18     freopen("a.out","w",stdout);
19 
20     scanf(LL,&n);
21     long long ans=0,tmp=0;
22     for (long long a=1,v;a*a<=(v=n/a);a++,ans++)
23         for (long long b=a+1;b*b<=v;b++)
24             tmp+=n/(a*b)-b;
25     ans+=tmp*6;
26     tmp=0;
27     for (long long a=1,v;(v=a*a)<=n;a++)  //考虑两个/三个数相等的情况 
28     {
29         tmp+=n/v;
30         if (a*a<=n/a) tmp--;
31     }
32     ans+=tmp*3;
33     printf(LL "\n",ans);
34 
35     return 0;
36 }
a100

今天的题解笔记就到这里,后两题太难了弃了。


Part2:数据结构专题

  • 常见的数据结构:
  1. 数组、链表
  2. 队列、栈
  3. 堆(仅需知道如何用priority_queue实现)
  4. 并查集
  5. 树状数组或线段树(掌握一个即可,线段树学习资料:线段树完整版
  6. 树上LCA(最近公共祖先,用倍增)
  7. DFS序列:把一棵二维的树通过DFS搜索顺序记录为线性序列,且每棵子树的所有节点都在这个序列上的一段连续区间上:

技术分享左图的DFS序列为:1 2 4 5 3 6 7   转换为线性后,就可以用线段树解决相关问题了:)

9.括号序列:依然基于DFS 【名称来源:+为左括号,-为右括号,则和为零是是合法的括号】

还是上面那个图,它的括号序列为:+1 +2 +4 -4 +5 -5 -2 +3 +6 -6 +7 -7 +8 -8 -3 -1

                                                             -4代表4已经遍历完了

 

 

清北学堂Day2

标签:sdn   print   lin   ext   log   16px   ref   unix   cstring   

原文地址:http://www.cnblogs.com/lulala/p/7622177.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!