上午模拟赛,普及组,居然才打250。。。伤心死
第四题二分思路完全正确,少加了一个判断语句100分就没了,哎。(但是,头一次用二分答案,估计以后就会熟练一些吧,我依然相信有O(t)的做法
提太水了,就不讲解了。
晚上把昨天那个逼疯我的题a了,(感觉有点卡常的嫌疑
问题 C: 分糖果
题目描述
玛西亚孤儿院的特蕾莎院长决定给孩子分糖吃。但是玛西亚孤儿院的孩子们希望所有人分得的糖果一样多,尤其是克拉姆,他不希望有不公平的事情发生。特蕾莎院长买来了n包糖果,第i包里面有ai个糖果。现在,特蕾莎院长希望找出一段连续的区间[l,r](这里规定l<=r,虽然这并不符合数学上区间的规定),使得这段区间的所有整包糖果都被等分成几个小包糖果,并使得每小包糖果数量最大,容易得出这个数量是gcd(al,al+1,...,ar)。但是特蕾莎院长并不会算,她想问问你,满足gcd(al,al+1,...,ar)=k的(l,r)二元组有多少个呢?
输入
第一行一个整数n。
第二行n个整数,第i个整数表示ai。
第三行一个整数q。
接下来q行,每行一个整数k,表示询问。
输出
输出共q行,每行一个整数,第i行表示第j个询问的答案。
样例输入
3 2 6 3 5 1 2 3 4 6
样例输出
1 2 2 0 1
提示
对于30%的数据,n<= 500, q<= 500。
对于60%的数据,n<= 500, q<= 100,000。
对于另20%的数据,n<= 100,000, q<= 300,000。保证数据随机生成。
对于100%的数据,n<= 100,000, q<= 300,000。
对于100%的数据,1<= ai,k <= 1000,000,000。
一看见数据范围,就觉得暴力应该是30分,如果预处理暴力60
但是要拿满分还是有点悬。
特别恶心的是,这道题要用rmq,二分这两个数据结构,(两个!
而且,时限很惊险,我用优化读入还tle90
先把代码粘上吧 哦对了,这道题的答案居然要用long long 也就是说个数会爆int(真的有点意外,但是作为提高组选手,这种失误不该发生吧
STL大法好,就是不开O2容易挂
#include<iostream> #include<cmath> #include<cstring> #include<algorithm> #include<cstdio> #include<queue> #include<map> using namespace std; #define ll long long map<int,ll>ma; int rmq[30][100001]; int readin(){ int x=0;char ch=getchar(); while(ch<'0'||ch>'9'){ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } int gcd(int a,int b){ if(b==0)return a; else return gcd(b,a%b); } //int a[100001]; int lg[100001]; int query(int l,int r){ if(l==r)return rmq[0][l]; int x=lg[r-l+1]; return gcd(rmq[x][l],rmq[x][r+1-(1<<x)]); } void erfen(int l,int r,int i){ int x=query(i,l),z=query(i,r); if(x==z){ ma[x]+=(r-l+1); return ; } if(r-l==1){ ma[x]+=1; ma[z]+=1; return ; } int mid=(l+r)>>1; int y=query(i,mid); if(x==y){ ma[x]+=(mid-l+1); erfen(mid+1,r,i); return ; } if(z==y){ ma[y]+=(r-mid+1); erfen(l,mid-1,i); return ; } else { erfen(l,mid,i); erfen(mid+1,r,i); } } int main(){ int n=readin(); // ma[1]=0; for(int i=1;i<=n;i++){ rmq[0][i]=readin(); //ma[rmq[0][i]]++; } for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1; for(int i=1;i<=lg[n];i++) for(int j=1;j<=n+1-(1<<i);j++) rmq[i][j]=gcd(rmq[i-1][j],rmq[i-1][j+(1<<(i-1))]); for(int i=1;i<n;i++){ //int l=i,r=n; erfen(i,n,i); } ma[rmq[0][n]]++; /*for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ int x=query(i,j); ma[x]++; } } */ int m=readin(); ll k; while(m--){ k=readin(); cout<<ma[k]<<endl; } }
具体思路很好想,难就难在怎么把这个超长的程序写对。而且还容易超时。
这个考试还是第二题难度比较大吧我认为。
截图留念