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 }
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 }
今天的题解笔记就到这里,后两题太难了弃了。
Part2:数据结构专题
左图的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已经遍历完了
原文:http://www.cnblogs.com/lulala/p/7622177.html