高一组模拟赛4 解题报告

时间:2019-09-12
本文章向大家介绍高一组模拟赛4 解题报告,主要包括高一组模拟赛4 解题报告使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

高一组模拟赛4 解题报告

T1 八卦

拿到这道题先看数据范围,,这么大的数据肯定就是数学公式了,推一波公式:

不妨倒过来想,看看不满足情况的可能性有多少,第一个人有m种不同的话题,那么第二个人就有m-1种,第三个人也是m-1种,根据乘法原理可知有 ,然后用总数 减去它就好了,然后上述式子可以用快速幂。

代码:

#include <bits/stdc++.h>
using namespace std;
const int P=10003;
long long n,m;
long long power1(long long a,long long b,long long p) {
    a%=p;
    long long ans=1%p;
    for(; b; b>>=1) {
        if(b&1) ans=ans*a%p;
        a=a*a%p;
    }
    return ans;
}
int main() {
    cin>>m>>n;
    long long num1=power1(m-1,n-1,P);
    long long num2=power1(m,n,P);
    num1=(num1*m)%P;
    cout<<(num2+P-num1)%P;
    return 0;
}

特别注意:在模n的意义下上述两式子相减可能为负数,所以在算的时候要在被减数上加一个模数P,,根据模运算的法则可知对结果没有影响。


T2线段

小数据显然是要求实现区间加,单点查询的一个结构。这不就是差分(线段树)么,关键在于最大的l和r范围在1e9之内,数组肯定会爆,但是n只有1e5,总共的数就是,可以离散化。

但是又有一个问题,那就是询问的点不一定正好在左右端点上,所以要离线处理,先把问题存下来,也将它离散,然后就查分就可以了,总共要存个数。

代码:

#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e5+10;
int n,q,l[N],r[N];
int a[N*3],c[N*3];
int sum[N*3],ans[N],L,R;
int m,tot,lpos,rpos,Q[N],num;
inline void discrete() {
    sort(a+1,a+tot+1);
    m=unique(a+1,a+tot+1)-(a+1);
}
inline int query(int x) {
    return lower_bound(a+1,a+m+1,x)-a;
}
int main() {
    cin>>n;
    for(int i=1; i<=n; i++) {
        cin>>l[i]>>r[i];
        a[++tot]=l[i];
        a[++tot]=r[i];
    }
    cin>>q;
    for(int i=1; i<=q; i++) {
        cin>>Q[i];
        a[++tot]=Q[i];
    }
    discrete();
    for(int i=1; i<=n; i++) {
        lpos=query(l[i]);
        rpos=query(r[i]);
        c[lpos]++;
        c[rpos+1]--;
    }
    for(int i=1; i<=m; i++) sum[i]=sum[i-1]+c[i];
    for(int i=1; i<=q; i++) {
        ans[++num]=sum[query(Q[i])];
    }
    for(int i=1; i<=num; i++) cout<<ans[i]<<endl;
    return 0;
}

T3身高

这道题...不说了,一个纯RMQ问题,用倍增,线段树都可以过。

代码:

#include <bits/stdc++.h>
using namespace std;
const int N=5e4;
int f1[N][20],f2[N][20],a[N];
int ans[N],tot;
int n,q,L,R;
void prework() {
    for(int i=1;i<=n;i++){
        f1[i][0]=a[i];
        f2[i][0]=a[i];
    }
    int t=log(n)/log(2)+1;
    for(int j=1;j<t;j++)
        for(int i=1;i<=n-(1<<j)+1;i++){
            f1[i][j]=max(f1[i][j-1],f1[i+(1<<(j-1))][j-1]);
            f2[i][j]=min(f2[i][j-1],f2[i+(1<<(j-1))][j-1]);
        }
}
int ask(int l,int r){
    int k=log(r-l+1)/log(2);
    return max(f1[l][k],f1[r-(1<<k)+1][k])-min(f2[l][k],f2[r-(1<<k)+1][k]);
}
int main() {
    cin>>n>>q;
    for(int i=1;i<=n;i++) cin>>a[i];
    prework();
    for(int i=1;i<=q;i++){
        cin>>L>>R;
        ans[++tot]=ask(L,R);
    }
    for(int i=1;i<=q;i++) cout<<ans[i]<<endl;
    return 0;
}

T4酒店

做法1:直接暴力枚举,,可以得到20分。

做法2:枚举+RMQ(ST表),,40分没问题了。

做法3:分析一下问题,如果顺着扫,扫到某种颜色,然后从它开始从右往左数,数到的第一个可行的酒店,那么在这个酒店之前的所有酒店都可行,通过这个,就可以得到的算法。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2e6+10;
unsigned long long n,k,p,b[N],d[N],sum[N],ans,temp,color,price;
template<class I>
inline void read(I &x) {
    x=0;
    char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') {
        x=(x<<3)+(x<<1)+(ch&15);
        ch=getchar();
    }
}
struct hotel {
    int c,p;
} a[N];
int main() {
    cin>>n>>k>>p;
    for(int i=1; i<=n; i++) {
        read(color);
        read(price);
        if(price<=p) temp=i;
        if(b[color]<=temp) d[color]=sum[color];
        ans+=d[color];
        sum[color]++;
        b[color]=i;
    }
    cout<<ans<<endl;
    return 0;
}

特别注意:如果要读入的数据量比较大,要用快读。

原文地址:https://www.cnblogs.com/wycxingchen/p/11513072.html