Contest1176 - 20180608限时练习

总结:开始理解错了题目的意思,所以花了时间却没有打出来,先做了C;
然后B题有思路,打完之后没有调出来,就换回A题,做出来了以后,再做B题主要还是pow的问题,后来再主攻D;D的想法很多,开始想了单调队列,不过打不出来;后来分治就通了。主要还是要注意时间的调配,分散精力的优点是可以顾全大局,但是对于题目思考的深度肯定是差了一点
P1611 A 中位数计数
简析:效率O(n^2),显然满足条件的区间必是含奇数个数的区间,对于每个数,先往右扫一遍,求得其右边比其大的和比其小的数的个数的差x,然后再往左扫一遍,求其左边比起小的数和比起大的数的差,若一个数在这个区间为中位数,则若其右边比它大的比比它小的多x(有点绕),则其左边相反小的要比大的多x,,说白了就是delta(x)l=delta(x)r
这样x才能正好在中间位置,用一个数组记录一下差值为某个数的个数即可,注意要算上这个数自己。

#include<bits/stdc++.h>
#define N 8005
using namespace std;
int n,a[N],has[N<<1];
int main(){
    while(~scanf("%d", &n)){
        for(int i=1;i<=n;i++)
           scanf("%d",&a[i]);
        for(int i=1;i<=n;i++){
            int cnt=0,ans=0;
            memset(has,0,sizeof(has));
            has[8000]++;
            for(int j=i+1;j<=n;j++){
                cnt+=a[j]>a[i]?1:-1;
                has[8000+cnt]++;
            }
            cnt=0;
            ans+=has[8000];
            for(int j=i-1;j>=1;j--){
                cnt+=a[j]<a[i]?1:-1;
                ans+=has[8000+cnt];
            }
            printf("%d%c",ans,i==n?'\n':' ');
        }
    }
}   

P1606 B 全X数字
简析:一道简单的裸题,就是快速幂求和,花了时间主要还是因为模板不熟练。

#include<bits/stdc++.h>
#define ll long long 
using namespace std; 
int cas; 
ll x,m,mod,c,ans; 
ll p[105],sum[105]; 
ll pow(ll k,int d) { 
    if(k==1) return 10; 
    if(p[d]!=-1) return p[d]; 
    ll s=(pow(k/2,d+1)*pow(k/2,d+1))%mod; 
    if(k%2==1) s=(s*10)%mod; 
    return p[d]=s; 
} 
ll getsum(ll k,int d) { 
    if(k==1) return 10; 
    if(sum[d]!=-1) return sum[d]; 
    ll s=((getsum(k/2,d+1)*pow(k/2,d+1))%mod+getsum(k/2,d+1))%mod; 
    if(k%2==1) s=(s+pow(k,d))%mod; 
    return sum[d]=s; 
} 
int main(){ 
    scanf("%d",&cas); 
    for(int i=1;i<=cas;i++) { 
        memset(sum,-1,sizeof(sum)); 
        memset(p,-1,sizeof(p)); 
        scanf("%lld%lld%lld%lld",&x,&m,&mod,&c); 
        m--; 
        ans=getsum(m,1)+1; 
        ans=(ans*x)%mod; 
        printf("Case #%d:\n",i); 
        if(ans%mod==c) printf("Yes\n");else printf("No\n"); 
    } 
    return 0; 
} 

P1608 C 瞬间移动
简析:试着推一下会发现他是杨辉三角(话说之前考试考过)
这里只需要求C(m-2,n-2+m-2)即可。之后用逆元就完事。:

#include<bits/stdc++.h>
#define ll long long
#define N 1000005
#define mod 1000000007
using namespace std;
int n,m;ll c[N];
void gcd(int a,int b,ll &x,ll &y){
    if (b==0){x=1;y=0;return;}
    gcd(b,a%b,y,x);
    y=y-(a/b)*x;
}
int main(){
    while (~scanf("%d%d",&n,&m)){
        c[0]=1;
        for (int i=1;i<=n+m-4;i++){
            ll x,y;gcd(i,mod,x,y);
            ll tmp=(x+mod)%mod;
            c[i]=(c[i-1]*(n+m-4-i+1))%mod;
            c[i]=(c[i]*tmp%mod)%mod;
        }
        printf("%lld\n",c[m-2]);
    }
}

P1607 D 区间的价值
简析:这道题用到了分治的思想(话说开始想过单调队列不过炸了)
首先,我们来定义solve(l,r)来求出区间[l,r]中各种区间长度的最大价值。
然后,我们找出[l,r]中的最小值。
固定了最小值以后,我们再去枚举最大值,算出各个价值。
我们能发现,随着区间变长,如果最小值是固定的,那么最大值只有可能越来越大,价值也会越来越大。
所以我们要把区间短的答案给区间长的更新。
如果最小值不是这一个呢?我们直接递归两边的就行了
我们再递归继续求solve(l,p-1)和solve(p+1,r),p是最小值的位置
由于数据是全随机的,所以不会退化到O(n^2)

#include<bits/stdc++.h>
#define ll long long
#define N 100005
using namespace std;
int n, a[N];
ll t[N], ans[N];
void solve(int l,int r) {
    if(l>r) return;
    int p=0;
    for(int i=l;i<=r;i++) 
        if(!p||a[i]<a[p])p=i;
    int w=r-l+1;
    for(int i=1;i<=w;i++)t[i]=0;
    for(int i=l;i<=p;i++)
        t[p-i+1]=max(t[p-i+1],(ll)a[p]*a[i]);
    for(int i=p;i<=r;i++)
        t[i-p+1]=max(t[i-p+1],(ll)a[p]*a[i]);
    ll pre=0;
    for(int i=1;i<=w;i++) {
        pre=max(pre,t[i]);
        ans[i]=max(ans[i],pre);
    }
    solve(l,p-1);solve(p+1,r);
}
int main() {
    while(~scanf("%d", &n)){
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        solve(1,n);
        for(int i=1;i<=n;i++)
            printf("%lld\n",ans[i]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值