「SWTR-07」IOI 2077

挺 SB 的,要不是我睡过头赛时就切了。

我习惯用 C(n,m) 表示 n 个数选 m 个数的方案。

因为 ai 升序,显然按 [l,k),(k,r] 去分。

考虑暴力,然而每种方案数很难算。换个角度,考虑一个数的贡献次数。

挺显然的,假如 i[l,k) 那么就是 C(kl,m1)×C(rk,m),即左右各选 m 包含这个数的方案数。 i(k,r] 同理。

再考虑 ak,显然每种方案都有它。

暴力 Code:

#include <cstdio> #include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <cmath> #include <queue> #include <map> #include <ctime> #define ll long long using namespace std; int rd() { int f=1,sum=0; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return sum*f; } ll lrd() { ll f=1,sum=0; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return sum*f; } #define mod 998244353 #define int ll int fpow(int x,int y) { int res=1; while(y) { if(y&1) res=res*x%mod; x=x*x%mod; y>>=1; } return res; } #define N (int)(2e6+5) int n,a[N],jie[N],djie[N],sum[N],m; int C(int n,int m) { if(m>n||m<0) return 0; return jie[n]*djie[m]%mod*djie[n-m]%mod; } int SUM(int l,int r) { return (((sum[r]-sum[l-1])%mod)+mod)%mod; } signed main() { jie[0]=djie[0]=1; for(int i=1;i<=(int)(2e6);i++) jie[i]=jie[i-1]*i%mod,djie[i]=fpow(jie[i],mod-2); rd(); n=rd(); m=rd(); for(int i=1;i<=n;i++) a[i]=rd(),sum[i]=(sum[i-1]+a[i])%mod; int ans=0; for(int mmm=1;mmm<=m;mmm++) { int l=rd(),r=rd(),k=rd(); int qwq=(r-l)/2,res=0; for(int i=0;i<=qwq;i++) { int r1=0,x=C(k-l-1,i-1)*C(r-k,i)%mod; //cout<<i<<" "<<x<<endl; r1+=SUM(l,k-1)*x%mod; x=C(k-l,i)*C(r-k-1,i-1)%mod; r1+=SUM(k+1,r)*x%mod; x=C(k-l,i)*C(r-k,i)%mod; r1+=x*a[k]%mod; r1=r1*fpow(x,mod-2)%mod; r1=(r1%mod+mod)%mod; // cout<<i<<" "<<r1<<endl; res=(res+r1)%mod; } res=res*fpow(qwq+1,mod-2)%mod; res=(res%mod+mod)%mod; // cout<<res<<endl; ans^=res; } printf("%lld",ans); return 0; }

显然我们不能枚举 m,考虑对式子拆开,单独看一个小部分。

假如我们看

SUM(l,k1)×C(kl1,i1)×C(rk,i)C(kl,i)×C(rk,i)

发现可以化掉

SUM(l,k1)i(kl)

那一切都挺显然的了。

#include <cstdio> #include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <cmath> #include <queue> #include <map> #include <ctime> #define ll long long using namespace std; int rd() { int f=1,sum=0; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return sum*f; } ll lrd() { ll f=1,sum=0; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return sum*f; } void pr(int x) { if(x<0) {putchar('-');x=-x;} if(x>9) pr(x/10); putchar(x%10+'0'); } const int mod=998244353; #define int ll int fpow(int x,int y) { int res=1; x%=mod; while(y) { if(y&1) res=res*x%mod; x=x*x%mod; y>>=1; } return res; } #define N (int)(2e6+5) int n,a[N],sum[N],INV[N],m; int SUM(int l,int r) { return (sum[r]-sum[l-1])%mod; } int SUM1(int l,int r) { return (r+l)*(r-l+1)%mod*fpow(2,mod-2)%mod; } int check(int n,int m) { return n>=m; } signed main() { rd(); n=rd(); m=rd(); for(int i=1;i<=n;i++) a[i]=rd(),sum[i]=(sum[i-1]+a[i])%mod; INV[0]=INV[1]=1; for(int i=2;i<=(int)(2e6);i++) INV[i]=INV[mod%i]*(mod-mod/i)%mod; int ans=0; for(int mmm=1;mmm<=m;mmm++) { int l=rd(),r=rd(),k=rd(); int qwq=(r-l)>>1,res=0; int qaq=min(qwq,min(k-l,r-k)); res+=SUM(l,k-1)*SUM1(0,qaq)%mod*INV[k-l]%mod; res%=mod; res+=SUM(k+1,r)*SUM1(0,qaq)%mod*INV[r-k]%mod; res%=mod; res+=(qaq+1)*a[k]%mod; res%=mod; res=res*INV[qwq+1]%mod; res=(res%mod+mod)%mod; // cout<<res<<endl; ans^=res; } printf("%lld",ans); return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/15872347.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示