牛客网暑期ACM多校训练营(第十场)D Rikka with Prefix Sum (组合数学)
生活随笔
收集整理的這篇文章主要介紹了
牛客网暑期ACM多校训练营(第十场)D Rikka with Prefix Sum (组合数学)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
https://www.nowcoder.com/acm/contest/148/D
題意
一個A數組,初始全為0。現有三種操作,1:給區間[L,R]+w;2:把每個位置的元素變為其前綴和;3:求區間[L,R]的和
分析
參考:http://www.cnblogs.com/tetew/p/9504595.html
看到題的時候慌了神,因為1、2操作的可能次數實在太大了,認為是什么巧妙的數據結構。。。
實則是組合數學,腦子不夠用啊。
首先我們討論一下對某個位置的數進行+w的操作后,會對后面有什么影響。
縱列看作是2操作的次數,橫排看作位置。45°斜著看,有點像楊輝三角!
于是,如果在(i,j)+w,那么對于位于其右下方的點(x,y)來說,貢獻為C(x-i+y-j-1,x-i-1)*w。
因為3操作不超過500次,我們記錄1和2的操作,對于每次3操作,再O(n)查詢。
求區間[L,R]的和時,可以直接solve(x+1,R)-solve(x+1,L-1),solve()是求前面所有的操作1和操作2的貢獻,并且要加上這一次的求前綴和的貢獻(所以是x+1)。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <algorithm> #include <cmath> #include <ctime> #include <vector> #include <queue> #include <map> #include <stack> #include <set> #include <bitset> using namespace std; typedef long long ll; typedef unsigned long long ull; #define ms(a, b) memset(a, b, sizeof(a)) #define pb push_back #define mp make_pair #define pii pair<int, int> #define eps 0.0000000001 #define IOS ios::sync_with_stdio(0);cin.tie(0); #define random(a, b) rand()*rand()%(b-a+1)+a #define pi acos(-1) const ll INF = 0x3f3f3f3f3f3f3f3fll; const int inf = 0x3f3f3f3f; const int maxn = 200000 + 100; const int maxm = 200000 + 10; const int mod = 998244353; ll fac[maxn],inv[maxn]; ll qpow(ll a,ll b){ll res=1;while(b){if(b&1) res=res*a%mod;b>>=1;a=a*a%mod;}return res; } void init(){fac[0]=1;for(int i=1;i<maxn;i++) fac[i]=fac[i-1]*i%mod;inv[maxn-1]=qpow(fac[maxn-1],mod-2);for(int i=maxn-2;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod; } ll C(int n,int m){if(m>n||m<0) return 0;return fac[n]*inv[m]%mod*inv[n-m]%mod; } struct ND{int x,pos,w; }a[maxn]; int cnt; ll cal(int x,int y){ll res=0;for(int i=1;i<=cnt;i++){if(a[i].x<=x&&a[i].pos<=y){res=(res+C(x-a[i].x+y-a[i].pos-1,x-a[i].x-1)*a[i].w%mod+mod)%mod;}}return res; } int main() { #ifdef LOCALfreopen("in.txt", "r", stdin); // freopen("output.txt", "w", stdout); #endifinit();int T;int n,m,op,x,y;scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);int now=1;cnt=0;while(m--){scanf("%d",&op);if(op==1){scanf("%d%d%d",&x,&y,&op);a[++cnt].x=now-1,a[cnt].pos=x,a[cnt].w=op;a[++cnt].x=now-1,a[cnt].pos=y+1,a[cnt].w=-op;}else if(op==2){now++;}else{scanf("%d%d",&x,&y);ll ans=(cal(now+1,y)-cal(now+1,x-1)+mod)%mod;printf("%lld\n",ans);}}}return 0; }?
轉載于:https://www.cnblogs.com/fht-litost/p/9563521.html
總結
以上是生活随笔為你收集整理的牛客网暑期ACM多校训练营(第十场)D Rikka with Prefix Sum (组合数学)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学习webpack4 - ES6语法转化
- 下一篇: Jmeter设置代理,抓包之app请求