NOIP模拟测试10「大佬·辣鸡·模板」
大佬
顯然假期望
我奇思妙想出了一個式子$f[i]=f[i-1]+\sum\limits_{j=1}^{j<=m} C_{k \times j}^{k}\times w[j]$
然后一想不對得容斥
于是我得到$f[i]=f[i-1]+\sum\limits_{j=1}^{j<=m} C_{j\times(k-1)}^{k-1} \times w[j]$
但還是不對
現在思考第一個式子為什么不對
我們枚舉矩陣選數
1 2 3
1 2 3
1 2 3
這樣我們C的話概率會很鬼$\frac {4}{12}$$\times$$\frac {3}{11}$$\times$$\frac {2}{10}$
顯然應該是$\frac 1 3$$\times $$\frac 1 3$$\times$$\frac 1 3$
我算小了
真的是小了嗎?
思考第二個式子為什么不對,顯然我們如果這樣做應該再乘$C_{k}^{1}$但這么乘起來會重復
1111111會被多貢獻很多回
還是要容斥
然后考試時我思維就停止了
我們或許可以換種思路考慮
同樣是一個區間,我們這樣算區間貢獻
$\sum\limits_{j=1}^{j<=m} j^k-(j-1)^k$
理解一下
$j^k$表示$<=j$隨便選,然后再容斥掉$(j-1)^k$(所有都比j小,選不到j)
得到貢獻
然后再用f轉移即可
#include<bits/stdc++.h> #define ll long long #define A 700000 using namespace std; const ll mod=1e9+7; ll n,m,k,sumday,w[A],ni,ans=0; inline ll meng(ll x,ll k){ll ans=1;for(;k;k>>=1,x=x*x%mod)if(k&1)ans=ans*x%mod;return ans; } int main(){scanf("%lld%lld%lld",&n,&m,&k);if(k>n) {puts("0");return 0;}ni=1;for(ll i=1;i<=m;i++)scanf("%lld",&w[i]);for(ll i=1;i<=m;i++)((ans=(ans%mod+(meng(i,k)%mod-meng(i-1,k)%mod+mod)*w[i]%mod)%mod))%=mod;ans=ans*(n-k+1)%mod;ni=meng(meng(m,k),mod-2)%mod;cout<<ans%mod*ni%mod<<endl; }?辣雞
考試歷程:
想到$n^2$過不了應該是$n^log$的,或許是$n^{log^2}$
反正$n^2$能過我吃掉鍵盤
然后我就思考,我tm應該用什么呢,CDQ?樹狀數組?線段樹?權值線段樹?還是像上次光那個題一樣的傻逼大模擬?
偶對了,一定是像光那個題一樣的傻逼題。
但我的光現在還沒有過啊。。
這個題暴力分好少啊
然后我還是打了個普通$n^2$然后發現它炸了。
我發現難以調出來還是改成了xy相關
考完后
這個題還真$n^2$能過
完了我沒有立flag
后來得知是優化過的$n^2$
打起來像插頭dp
首先矩陣內的貢獻我們可以用(x2-x1)*(y2-y1)*2算出來
然后矩陣之間分很多種情況
然而每一種都比較簡單,比插頭簡單的多
方格表示過于,,,容易出現各種錯誤,格點表示
?
具體還是看代碼
#include<bits/stdc++.h> using namespace std; #define ll long long #define A 1100000 struct node{ll x1,x2,y1,y2;friend bool operator <(const node a,const node b){return ((a.x1==b.x1)?a.y1<b.y1:a.x1<b.x1);} }nd[A]; ll ans=0,n; int main(){scanf("%lld",&n);for(ll i=1;i<=n;i++){scanf("%lld%lld%lld%lld",&nd[i].x1,&nd[i].y1,&nd[i].x2,&nd[i].y2);ans+=(nd[i].x2-nd[i].x1)*(nd[i].y2-nd[i].y1)*2;}sort(nd+1,nd+n+1);for(ll i=1;i<n;i++){for(ll j=i+1;j<=n;j++){if(nd[j].x1>nd[i].x2+1) break;if(nd[i].y2+1<nd[j].y1||nd[i].y1-1>nd[j].y2) continue; // printf("ix1=%lld iy1=%lld jx1=%lld jy1=%lld\n",nd[i].x1,nd[i].y1,nd[j].x1,nd[j].y1);if(nd[j].x1>nd[i].x2){if(nd[i].y2<nd[j].y1||nd[i].y1>nd[j].y2) ans++;else if(nd[i].y1==nd[j].y1){if(nd[i].y2==nd[j].y2)ans+=(nd[i].y2-nd[i].y1)*2;else if(nd[i].y2<nd[j].y2) ans+=(nd[i].y2-nd[i].y1)*2+1;else if(nd[i].y2>nd[j].y2)ans+=(nd[j].y2-nd[i].y1)*2+1;}else if(nd[i].y2==nd[j].y2){if(nd[i].y1==nd[j].y1)ans+=(nd[i].y2-nd[j].y1)*2;else if(nd[i].y1<nd[j].y1)ans+=(nd[i].y2-nd[j].y1)*2+1;else if(nd[i].y1>nd[j].y1)ans+=(nd[i].y2-nd[i].y1)*2+1;}else if(nd[i].y2>nd[j].y2&&nd[i].y1<nd[j].y1)ans+=(nd[j].y2-nd[j].y1)*2+2;else if(nd[i].y2<nd[j].y2&&nd[i].y1<nd[j].y1)ans+=(nd[i].y2-nd[j].y1)*2+2;else if(nd[i].y2>nd[j].y2&&nd[i].y1>nd[j].y1)ans+=(nd[j].y2-nd[i].y1)*2+2;else if(nd[i].y2<nd[j].y2&&nd[i].y1>nd[j].y1)ans+=(nd[i].y2-nd[i].y1)*2+2; // printf("second%lld\n",ans); }else{if(nd[i].x1==nd[j].x1){if(nd[i].x2==nd[j].x2)ans+=(nd[i].x2-nd[i].x1)*2;else if(nd[i].x2<nd[j].x2) ans+=(nd[i].x2-nd[i].x1)*2+1;else if(nd[i].x2>nd[j].x2)ans+=(nd[j].x2-nd[i].x1)*2+1;}else if(nd[i].x2==nd[j].x2){if(nd[i].x1==nd[j].x1)ans+=(nd[i].x2-nd[j].x1)*2;else if(nd[i].x1<nd[j].x1)ans+=(nd[i].x2-nd[j].x1)*2+1;else if(nd[i].x1>nd[j].x1)ans+=(nd[i].x2-nd[i].x1)*2+1;}else if(nd[i].x2>nd[j].x2)ans+=(nd[j].x2-nd[j].x1)*2+2;else if(nd[i].x1<nd[j].x1&&nd[i].x2<nd[j].x2)ans+=(nd[i].x2-nd[j].x1)*2+2; // printf("frist%lld\n",ans); } // printf("i=%lld j=%lld ans=%lld\n",i,j,ans); }}cout<<ans<<endl; }?模板
我一開始確實以為是模板
然后就開始打了,樹差,線段樹,權值線段樹,合并往上仍
不就是和雨天的尾巴差不多的一道題目嗎 AC預訂
然后越想越不對,覺得難以維護桶
看數據范圍不維護桶勉強可以70分
那就先得70分吧
然后我就打炸了,看著最后時間將至趕緊刪了打暴力
暴力樹上差分還有30分,樹上差分打對就行
然后樹上差分我覺得也不行,也是相當難維護,set,vector,map,multiset往上仍,但無濟于事
最小的點是10 10 10,打個純暴力還有10分呢
我成功奶死了自己
0分!
tqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltqltql
說一下這個怎么做
前置知識:
啟發式合并
線段樹
?
注意很多細節,我會在啟發式合并中具體講
轉載于:https://www.cnblogs.com/znsbc-13/p/11264230.html
總結
以上是生活随笔為你收集整理的NOIP模拟测试10「大佬·辣鸡·模板」的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 苏州园林是谁的府邸
- 下一篇: 给APK签名,修改签名