11.30 模拟赛

11.30 模拟赛

T1

题面node

​ 在一场奇怪的梦里,小Y来到了一个神奇的国度。这个国度能够用一根数轴表示,小Y在\(N\)处,而小Y想吃的美食在\(K\)处。c++

​ 小Y有两种方式移动,一种叫作步行,一种叫作瞬移。对于每次步行操做,小Y能够从\(x\)移动到\(x+1\)或者\(x-1\),而对于每次瞬移操做小Y能够从\(x\)瞬移到\(2x\)。那么小Y最少要移动多少次才能到达\(K\)处吃到食物呢?数据结构

【数据范围】\(0\le N,K\le 100,000\)优化

题解spa

水题。只须要bfs计算每一个点的最短路程便可。首先不可能走到负数点(必定不须要);其次不可能走到超过2e5的点(更多的必定会远离),所以能够肯定较紧的边界\([0,200000]\)code


思考:4min 实现:10min;排序

预计100 实际:90ci

没看到小于等于,边界设定为了\(>0\),结果挂了第三个点(\(N=100000,K=0\)input

AC代码:it

#include<bits/stdc++.h>
using namespace std;
const int N=200009,INF=0x3f3f3f3f;
typedef pair<int,int> P;
int n,k,f[N];
bool v[N];
int main(){
    freopen("meet.in","r",stdin);
    freopen("meet.out","w",stdout);
    scanf("%d%d",&n,&k);
    memset(f,INF,sizeof(f));
    queue<P> que;
    que.push(make_pair(n,0));
    while(!que.empty()){
        P now=que.front();
        que.pop();
        int pos=now.first,val=now.second;
        //cout<<pos<<endl; 
        v[pos]=true;
        f[pos]=min(f[pos],val);
        /*WA: pos-1>0*/
        if(pos-1>=0&&pos-1<N&&!v[pos-1]) 
            que.push(make_pair(pos-1,val+1));
        if(pos+1>=0&&pos+1<N&&!v[pos+1]) 
            que.push(make_pair(pos+1,val+1));
        if(pos*2>=0&&pos*2<N&&!v[pos*2]) 
            que.push(make_pair(pos*2,val+1));
    }
    cout<<f[k]<<endl;
    return 0;
}

T2

题面

给定长度为\(n\)的序列\(a_1,\dots,a_n\),定义一次操做为:

  1. 定义序列\(S\)\(a\)的前缀和;
  2. \(S\)复制回\(a\)

给定整数\(k\),求对\(a\)进行\(k\)此操做后的序列,对\(10^9+7\)取模。

题解

Subtask:

1~8 暴力

1~20 矩阵快速幂+对称性优化

19~22 每次操做的系数在杨辉三角中右下移一格 组合数表示便可

正解:

操做后序列每一项都是由前\(i\)个数乘上系数之和,而系数正好就是\(a[i]=1\)中答案序列倒过来

所以只要在19~22上加权便可

若是直接每次算组合数会超时,因此须要用前一项来推有一项


看了5分钟以为应该就是考虑每一项对总答案的贡献系数,因此想到\(a_i\)是由\(a_1,a_2,\dots,a_i\)乘上系数起来的就能够了。实际作的时候发现这个系数很难求,当时想的是高阶等差数列,可是又没有求和公式,因此就不会作了

其实系数的规律已经发现了 只须要看到是组合数而不仅是高阶等差数列就A掉了)

最后写了个递推暴力 过了8个点(\(f[i][j]=f[i-1][j]+f[i][j-1]\)

还在想是否是须要优化这个递推过程

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N=5009,K=1009,P=1e9+7;
typedef long long ll;
ll n,k,a[N];
ll b[N],c[N]; //b记录答案,c记录系数
void input(){
    scanf("%lld%lld",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
}
ll qpow(ll x,ll y){
    ll res=1,tmp=x;
    while(y){
        if(y&1) res=(res*tmp)%P;
        tmp=(tmp*tmp)%P;
        y>>=1;
    }
    return res;
}
void solve(){
    //for(int i=1;i<=n;i++)
       // c[i]=C(i-1,k+i-2);
    //原来的C(x,y)用于计算组合数,但会超时,所以改成递推
    c[1]=1;
    for(int i=2;i<=n;i++)
        c[i]=(((c[i-1]*(k+i-2))%P)*qpow(i-1,P-2))%P;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=i;j++)
            b[i]=(b[i]+a[j]*c[i-j+1])%P;
    for(int i=1;i<=n;i++)
        printf("%d ",b[i]);
}
int main(){
    freopen("sum.in","r",stdin);
    freopen("sum.out","w",stdout);
    input();
    /*if(k<=1000) solvedp();
    else*/ solve();
    return 0;
}

T3

题面

​ 恋之微风·小乔,是手游《王者荣耀》中的法师型英雄,擅长远程消耗。小乔有一把神奇的扇子,借助灵活的走位能够对敌人形成高额的伤害。小乔是小 A 最喜欢(会玩)的英雄之一。在一场梦里,小 A 与小乔来到了一个异次元世界。

​ 异次元世界位于极坐标系中。小乔定义了一个值\(m\),以等分\([-\pi,\pi]\)弧度。小乔利用她神奇的扇子,进行\(n\)次“绽开之舞“操做。对于第\(i\)次“绽 放之舞”操做,小乔将设定半径\(r_i\),起始位置\(s_i\),终止位置\(t_i\),她借助本身神奇 的扇子,以坐标系原点为圆心,\(r_i\)为半径,将圆心角\(\dfrac{\pi s_i}{m}\)到圆心角\(\dfrac{\pi t_i}{m}\)这部分扇形区域逆时针叠加一层“治愈微笑”。

​ 小乔想到了一个有趣(奇怪)的问题,她但愿知道有多大面积的区域被叠加 过至少\(k\)层“治愈微笑”。这个问题难倒了平日里善于发现并解决问题的小 A,现 在小 A 求助于你,但愿你能帮他解决这个问题。

​ 咱们设答案的值为\(T\),为了方便表达,你只须要输出\(T\cdot \dfrac{2m}{\pi}\)(能够证实这是 一个非负整数)的值便可。

题解

将扇形的起始边和结束边排序,将圆周分红\(O(n)\)个部分。考虑一个区间时,将覆盖此区间的全部扇形取出,求出第\(k\)大的扇形,其覆盖面积就是符合条件的面积(由于较大的扇形必定覆盖较小的梯形)。

支持查询第\(k\)大数并能够插入和删除的数据结构我选用的是BIT(平衡树也能够)

须要注意\(t_i\)可能小于\(s_i\)


一开始想的是扫描线 可是想不清楚

而后就去写了暴力和差分的部分分 结果差分写挂了

订正的时候由于C++不知道什么诡异的断定机制调了很久

包括但不只限于node(6行)里面的int改为ll就挂;在添加节点(35行)时若是不用tmp就会断定错误等等等等)

后面发现是在改ll的时候忘了把%d改为%lld了……

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N=200009;
typedef long long ll;
ll n,m,k,r[N],s[N],t[N],bit[N<<1];
struct node{
    ll p,v,r; //pos,val(-1/1),radius
    bool operator < (const node &a)const{
        return p<a.p;
    }
} h[N<<1];
void input(){
    cin>>n>>m>>k;
    for(ll i=1;i<=n;i++)
        scanf("%lld%lld%lld",&r[i],&s[i],&t[i]);
}
void upd(ll pos,ll val){
    while(pos<=N){
        bit[pos]+=val;
        pos+=(pos&-pos);
    }
}
ll query(ll pos){
    ll res=0;
    while(pos){
        res+=bit[pos];
        pos-=(pos&-pos);
    }
    return res;
}
void solve(){
    for(ll i=1;i<=n;i++)
        s[i]+=m+1,t[i]+=m+1;
    int tot=0;
    for(ll i=1;i<=n;i++){
    	int tmp=s[i]-t[i];
        if(tmp<0){
            h[++tot]=(node){s[i],1,r[i]};
			h[++tot]=(node){t[i],-1,r[i]};
		}
        else{
            h[++tot]=(node){1,1,r[i]};
			h[++tot]=(node){t[i],-1,r[i]};
            h[++tot]=(node){s[i],1,r[i]};
			h[++tot]=(node){2*m+1,-1,r[i]};
        }
    }
    sort(h+1,h+tot+1);
    ll ans=0,cnt=0;
    for(ll i=1;i<=tot-1;i++){
        upd(h[i].r,h[i].v);
        cnt+=h[i].v;
        if(cnt<k) continue;
        ll l=1,r=N-1;
        while(l!=r){
            ll mid=(l+r)>>1;
            ll tmp=cnt-query(mid)+1;
            if(tmp>k) l=mid+1;
            else r=mid;
        }
        ans+=l*(h[i+1].p-h[i].p)*l;
    }
    cout<<ans<<endl;
}
int main(){
    freopen("xiaoqiao.in","r",stdin);
    freopen("xiaoqiao.out","w",stdout);
    input();
    /*if(n<=100) solveBF();
    else solveT();*/
    solve();
    return 0;
}
相关文章
相关标签/搜索