周日

Posted on 2017-06-18 22:05  Amphetamine  阅读(231)  评论(0编辑  收藏  举报

上午模拟赛,普及组,居然才打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;
    }
} 
View Code

 

具体思路很好想,难就难在怎么把这个超长的程序写对。而且还容易超时。

这个考试还是第二题难度比较大吧我认为。

截图留念