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;
}
相關文章
相關標籤/搜索