題面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; }
題面
給定長度爲\(n\)的序列\(a_1,\dots,a_n\),定義一次操做爲:
給定整數\(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; }
題面
戀之微風·小喬,是手遊《王者榮耀》中的法師型英雄,擅長遠程消耗。小喬有一把神奇的扇子,藉助靈活的走位能夠對敵人形成高額的傷害。小喬是小 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; }