首页 > 编程语言 >2024“钉耙编程”中国大学生算法设计超级联赛(1)

2024“钉耙编程”中国大学生算法设计超级联赛(1)

时间:2024-07-19 21:07:15浏览次数:13  
标签:钉耙 CI now const int 编程 2024 include define

Preface

唐完了的一集,被前中期题花式腐乳以至于中期一度被同校队伍打出 \(n+3\)

最后 4h 时堪堪写完 8 个题,最后 1h 冲刺众数那个题然后写一半方法假了直接下班

当然还有个难绷的是传送那个题和我今年给新生拉的数据结构专题的一个题几乎一样,把代码拉来改下输入输入就过了,12min 抢到一血可海星


循环位移

徐神刚开始写了个 SAM 然后发现被卡空间了,然后后面一顿修改 WA 了两发后红温了,就喊我上去写了个 Hash

Hash 的做法就非常无脑,把 \(A\) 的所有循环位移串的 Hash 值扔进 set 里,然后枚举 \(B\) 的所有长为 \(|A|\) 的子串检验即可

#include<cstdio>
#include<iostream>
#include<set>
#include<cstring>
#define RI register int
#define CI const int&
using namespace std;
typedef long long LL;
const int N=2100000,mod1=998244353,mod2=1e9+7;
struct Hasher
{
    int x,y;
    inline Hasher(CI X=0,CI Y=0)
    {
        x=X; y=Y;
    };
    inline LL val(void)
    {
        return ((1LL*x)<<31LL)|(1LL*y);
    }
    friend inline Hasher operator + (const Hasher& A,const Hasher& B)
    {
        return Hasher((A.x+B.x)%mod1,(A.y+B.y)%mod2);
    }
    friend inline Hasher operator - (const Hasher& A,const Hasher& B)
    {
        return Hasher((A.x-B.x+mod1)%mod1,(A.y-B.y+mod2)%mod2);
    }
    friend inline Hasher operator * (const Hasher& A,const Hasher& B)
    {
        return Hasher(1LL*A.x*B.x%mod1,1LL*A.y*B.y%mod2);
    }
}h[N],pw[N]; int t; char a[N],b[N];
const Hasher seed=(31,131);
inline Hasher get_hash(CI l,CI r)
{
    return h[r]-h[l-1]*pw[r-l+1];
}
int main()
{
    for (scanf("%d",&t);t;--t)
    {
        scanf("%s%s",a+1,b+1); int n=strlen(a+1),m=strlen(b+1);
        RI i; for (i=1;i<=n;++i) a[n+i]=a[i];
        for (pw[0]=Hasher(1,1),i=1;i<=2*n;++i) pw[i]=pw[i-1]*seed;
        for (i=1;i<=2*n;++i) h[i]=h[i-1]*seed+Hasher(a[i]-'A',a[i]-'A');
        set <LL> ext; for (i=1;i<=n;++i) ext.insert(get_hash(i,i+n-1).val());
        for (i=1;i<=m;++i) h[i]=h[i-1]*seed+Hasher(b[i]-'A',b[i]-'A');
        int ans=0; for (i=1;i+n-1<=m;++i) ans+=ext.count(get_hash(i,i+n-1).val());
        printf("%d\n",ans);
    }
    return 0;
}

星星

暴力背包 DP 即可,注意枚举的界写的紧一点不然可能会 TLE

#include<bits/stdc++.h>
using namespace std;
#define int long long

const int INF = (int)1e18+5;

const int N = 4005;
int t, n, k;
int dp[N];
int wt[5];
signed main(){
    ios::sync_with_stdio(0); cin.tie(0);
    cin >> t;
    while (t--){
        cin >> n >> k;
        for (int i=0; i<=k; ++i) dp[i]=INF;
        dp[0] = 0;
        for (int i=1; i<=n; ++i){
            cin >> wt[1] >> wt[2] >> wt[3] >> wt[4];
            for (int w=4*i; w>=0; --w){
                for (int j=4; j>0; --j){
                    if (w-j<0) continue;
                    dp[w] = min(dp[w-j]+wt[j], dp[w]);
                }
            }
        }
        cout << dp[k] << '\n';
    }
    return 0;
}

很套路的题,考虑已经维护出了一个集合的答案,往其中加入一个数 \(x\) 会发生什么

通过分类讨论来去除 \(\max\) 的影响,讨论集合中一个数 \(y\) 的贡献:

  • \(y\le x\) 时,贡献为 \(x\times (x-y)\),需要求出集合中 \(\le x\) 的数的数量以及 \(\le x\) 的数的和;
  • \(y>x\) 时,贡献为 \(y\times (y-x)\),需要求出集合中 \(> x\) 的数的和以及 \(> x\) 的数的平方和;

通过 DSU on Tree 以及树状数组,可以做到小常数的 \(O(n\log^2 n)\)

#include<cstdio>
#include<iostream>
#include<vector>
#define RI register int
#define CI const int&
using namespace std;
typedef unsigned long long u64;
const int N=1e6+5;
int n,m,x,y,a[N],sz[N],son[N]; vector <int> v[N]; u64 ans,ret;
class Tree_Array
{
    private:
        u64 bit[N];
    public:
        #define lowbit(x) (x&-x)
        inline void upt(RI x,const u64& y)
        {
            for (;x<=m;x+=lowbit(x)) bit[x]+=y;
        }
        inline u64 get(RI x,u64 ret=0)
        {
            for (;x;x-=lowbit(x)) ret+=bit[x]; return ret;
        }
        inline u64 query(CI l,CI r)
        {
            if (l>r) return 0ull; return get(r)-get(l-1);
        }
        #undef lowbit
}CNT,SUM,SQR;
inline void DFS(CI now=1,CI fa=0)
{
    sz[now]=1; for (auto to:v[now]) if (to!=fa)
    if (DFS(to,now),sz[now]+=sz[to],sz[to]>sz[son[now]]) son[now]=to;
}
inline void work(CI x,CI sgn)
{
    u64 dlt=(CNT.query(1,a[x])*a[x]-SUM.query(1,a[x]))*a[x]+SQR.query(a[x]+1,m)-SUM.query(a[x]+1,m)*a[x];
    if (sgn>0) ret+=dlt; else ret-=dlt;
    CNT.upt(a[x],u64(sgn)); SUM.upt(a[x],u64(sgn)*a[x]); SQR.upt(a[x],u64(sgn)*a[x]*a[x]);
}
inline void travel(CI now,CI fa,CI mv)
{
    work(now,mv); for (auto to:v[now]) if (to!=fa) travel(to,now,mv);
}
inline void DSU(CI now=1,CI fa=0,CI flag=1)
{
    for (auto to:v[now]) if (to!=fa&&to!=son[now]) DSU(to,now,0);
    if (son[now]) DSU(son[now],now,1);
    for (auto to:v[now]) if (to!=fa&&to!=son[now]) travel(to,now,1);
    work(now,1); ans^=2ull*ret; //printf("%d = %llu\n",now,2ull*ret);
    if (!flag) travel(now,fa,-1);
}
int main()
{
    RI i; for (scanf("%d",&n),i=1;i<n;++i)
    scanf("%d%d",&x,&y),v[x].push_back(y),v[y].push_back(x);
    for (i=1;i<=n;++i) scanf("%d",&a[i]),m=max(m,a[i]);
    return DFS(),DSU(),printf("%llu",ans),0;
}

传送

很经典的线段树分治+可撤销并查集+懒标记维护

对时间分治后考虑在线段树的叶子节点将 \(1\) 所在的联通块的根节点打上对应时间的标记,在并查集撤销时将标记下传即可

#include<cstdio>
#include<iostream>
#include<vector>
#include<utility>
#define RI register int
#define CI const int&
using namespace std;
typedef long long LL;
typedef pair <int,int> pi;
const int N=600005;
struct Data
{
	int x,y,szy;
	inline Data(CI X=0,CI Y=0,CI SZY=0)
	{
		x=X; y=Y; szy=SZY;
	}
}stk[N*20]; int n,m,l[N],r[N],x,y,a,b,top,fa[N],sz[N]; LL tag[N];
inline int getfa(CI x)
{
	return fa[x]!=x?getfa(fa[x]):x;
}
inline void merge(int x,int y)
{
	x=getfa(x); y=getfa(y); if (x==y) return;
	if (sz[x]>sz[y]) swap(x,y); stk[++top]=Data(x,y,sz[y]);
	fa[x]=y; sz[y]+=sz[x]==sz[y]; tag[x]-=tag[y];
}
inline void revoke(CI tmp)
{
	while (top>tmp)
	{
		int x=stk[top].x,y=stk[top].y,szy=stk[top].szy;
		--top; fa[x]=x; sz[y]=szy; tag[x]+=tag[y];
	}
}
class Segment_Tree
{
	private:
		vector <pi> v[N<<2];
	public:
		#define TN CI now=1,CI l=1,CI r=n
		#define LS now<<1,l,mid
		#define RS now<<1|1,mid+1,r
		inline void insert(CI beg,CI end,const pi& it,TN)
		{
			if (beg<=l&&r<=end) return v[now].push_back(it); int mid=l+r>>1;
			if (beg<=mid) insert(beg,end,it,LS); if (end>mid) insert(beg,end,it,RS);
		}
		inline void solve(TN)
		{
			int tmp=top; for (auto [x,y]:v[now]) merge(x,y);
			if (l==r) return tag[getfa(1)]+=l,revoke(tmp);
			int mid=l+r>>1; solve(LS); solve(RS); revoke(tmp);
		}
		#undef TN
		#undef LS
		#undef RS
}SEG;
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i; for (scanf("%d%d",&n,&m),i=1;i<=n;++i) fa[i]=i,sz[i]=1;
	for (i=1;i<=m;++i)
	{
		scanf("%d%d%d%d",&x,&y,&a,&b);
		SEG.insert(a,b,make_pair(x,y));
	}
	LL ans=0; for (SEG.solve(),i=1;i<=n;++i) ans^=tag[i];
	return printf("%lld",ans),0; 
}

博弈

徐神敏锐地观察发现当且仅当出现次数为奇数的字符有 \(\le 1\) 个时可能会打到最后一轮,否则游戏总会提前结束并且由于对称性,两人的胜率都是 \(\frac{1}{2}\)

否则分情况讨论,当所有字符出现次数均为偶数时,只需算出平局的概率 \(p_1\),则获胜的概率为 \(\frac{1-p_1}{2}\)

当存在恰好一种字符出现次数为奇数时,算出除去一个该字符后平局的概率 \(p_2\),则获胜的概率为 \(\frac{1+p_2}{2}\)

\(p_1,p_2\) 都容易用组合意义推出表达式,这里不再赘述

#include <bits/stdc++.h>

using llsi = long long signed int;
constexpr int $n = 10000007;

constexpr llsi mod = 998244353;

constexpr llsi ksm(llsi a, llsi b) {
    llsi res = 1;
    while(b) {
        if(b & 1) res = res * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return res;
}

int fac[$n] = {1}, facinv[$n];

llsi C(const std::vector<int> S, bool inv = false) {
    llsi tot = 0, res = 1;

    if(inv) for(auto c: S) {
        res = res *    fac[c] % mod;
        tot += c;
    } else for(auto c: S) {
        res = res * facinv[c] % mod;
        tot += c;
    }

    if(inv) return facinv[tot] * res % mod;
    else    return fac[tot]    * res % mod;
}

int main() {
    std::ios::sync_with_stdio(false);
    for(int i = 1; i <= 10000000; ++i) fac[i] = llsi(fac[i - 1]) * i % mod;
    facinv[10000000] = ksm(fac[10000000], mod - 2);
    for(int i = 10000000; i >= 1; --i) facinv[i - 1] = llsi(facinv[i]) * i % mod;
    // std::cout << 1ll * fac[10] * facinv[8] % mod << char(10);

    constexpr llsi inv2 = ksm(2, mod - 2);

    int T; std::cin >> T; while(T--) {
        int n; std::cin >> n;
        int odd_count = 0;
        std::vector<int> a(n);
        std::string _;
        for(auto &a: a) std::cin >> _ >> a, odd_count += (a & 1);

        if(odd_count >= 2) {
            std::cout << inv2 << char(10);
            continue;
        }

        llsi p = C(a, true);
        for(auto &a: a) a /= 2;
        p = p * C(a, false) % mod;
        
        if(odd_count) {
            std::cout << ((mod + 1 - p) * inv2 % mod + p) % mod << char(10);
        } else {
            std::cout << (mod + (mod + 1 - p) * inv2 % mod) % mod << char(10);
        }
    }

    return 0;
}


序列立方

很有思维含量的一个题,总感觉我做过平方版本的题目来着,这题就是把平方的做法搬过来

考虑将原问题抽象为以下问题:在序列中选出三个相同的子序列,它们相同的方案数

不难发现这个问题可以 DP 求解,令 \(f_{i,j,k}\) 表示当前三个子序列的末尾分别为 \(a_i,a_j,a_k\) 的方案数,暴力转移显然是枚举 \(a_x=a_y=a_z\) 的 \((x,y,z)\) 并转移

但这样是 \(O(n^6)\) 的,后面徐神发现可以用高维前缀和优化该过程,即可将复杂度降为 \(O(n^3)\)

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=255,mod=998244353;
int n,a[N],f[N][N][N];
inline void inc(int& x,CI y)
{
    if ((x+=y)>=mod) x-=mod;
}
inline void dec(int& x,CI y)
{
    if ((x-=y)<0) x+=mod;
}
int main()
{
    RI i,j,k; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&a[i]);
    f[0][0][0]=1; int ans=0;
    for (i=1;i<=n;++i) for (j=1;j<=n;++j) for (k=1;k<=n;++k)
    {
        inc(f[i][j][k],f[i-1][j][k]);
        inc(f[i][j][k],f[i][j-1][k]);
        inc(f[i][j][k],f[i][j][k-1]);
        dec(f[i][j][k],f[i-1][j-1][k]);
        dec(f[i][j][k],f[i-1][j][k-1]);
        dec(f[i][j][k],f[i][j-1][k-1]);
        inc(f[i][j][k],f[i-1][j-1][k-1]);
        if (a[i]==a[j]&&a[i]==a[k])
        {
            inc(ans,f[i][j][k]);
            inc(f[i+1][j+1][k+1],f[i][j][k]);
        }
        
    }
    return printf("%d",ans),0;
}

三元环

比赛的时候失了智没想到题解中这么显然的容斥做法,鉴定为纯纯的彩笔

由于这个图是个竞赛图,那么任意选出三个点,它们要么构成三元环,要么存在一个点入度为 \(2\) 就构不成三元环

令 \(in_i\) 表示点 \(i\) 的入度,则答案为 \(C_n^3-\sum_{i=1}^n C_{in_i}^2\),计算 \(in_i\) 可以转化为经典的三维偏序求解

#include<cstdio>
#include<iostream>
#include<algorithm>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
const int N=200005;
struct ifo
{
	int f,g,id;
	friend inline bool operator < (const ifo& A,const ifo& B)
	{
		return A.f<B.f;
	}
}p[N]; int n,f[N],g[N],in[N];
class Tree_Array
{
	private:
		int bit[N];
	public:
		#define lowbit(x) (x&-x)
		inline int get(RI x,int ret=0)
		{
			for (;x;x-=lowbit(x)) ret+=bit[x]; return ret;
		}
		inline void add(RI x,CI y)
		{
			for (;x<=n;x+=lowbit(x)) bit[x]+=y;
		}
		inline void output(void)
		{
			for (RI i=1;i<=n;++i) printf("%lld%c",bit[i]," \n"[i==n]);
		}
		#undef lowbit
}BIT;
inline void solve0(void)
{
	RI i; for (i=n;i>=1;--i) in[i]+=BIT.get(f[i]),BIT.add(f[i],1);
	for (i=1;i<=n;++i) BIT.add(f[i],-1);
	for (i=n;i>=1;--i) in[i]+=BIT.get(g[i]),BIT.add(g[i],1);
	for (i=1;i<=n;++i) BIT.add(g[i],-1);
}
inline void solve1(CI l=1,CI r=n)
{
	if (l>=r) return; int mid=l+r>>1;
	solve1(l,mid); solve1(mid+1,r);
	sort(p+l,p+mid+1); sort(p+mid+1,p+r+1);
	RI i,j; for (i=l,j=mid+1;j<=r;++j)
	{
		while (i<=mid&&p[i].f<p[j].f) BIT.add(p[i++].g,1);
		in[p[j].id]+=BIT.get(p[j].g-1);
	}
	for (j=l;j<i;++j) BIT.add(p[j].g,-1);
}
inline void solve2(CI l=1,CI r=n)
{
	if (l>=r) return; int mid=l+r>>1;
	solve2(l,mid); solve2(mid+1,r);
	sort(p+l,p+mid+1); sort(p+mid+1,p+r+1);
	RI i,j; for (i=l,j=mid+1;i<=mid;++i)
	{
		while (j<=r&&p[i].f>=p[j].f) BIT.add(p[j++].g,1);
		in[p[i].id]-=BIT.get(p[i].g);
	}
	for (i=mid+1;i<j;++i) BIT.add(p[i].g,-1);
}
signed main()
{
	RI i; for (scanf("%lld",&n),i=1;i<=n;++i) scanf("%lld",&f[i]);
	for (i=1;i<=n;++i) scanf("%lld",&g[i]); solve0();
	for (i=1;i<=n;++i) p[i].f=f[i],p[i].g=g[i],p[i].id=i; solve1();
	for (i=1;i<=n;++i) p[i].f=f[i],p[i].g=g[i],p[i].id=i; solve2();
	long long ans=1LL*n*(n-1)*(n-2)/6LL;
	for (i=1;i<=n;++i) ans-=1LL*in[i]*(in[i]-1)/2LL;
	//for (i=1;i<=n;++i) printf("%lld%c",in[i]," \n"[i==n]);
	return printf("%lld",ans),0;
}

位运算

签到,不难发现每一位独立,预处理下这一位为 \(0/1\) 的方案数即可

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
int t,n,k,w[2];
int main()
{
    RI i; for (RI i=0;i<2;++i)
    for (int a=0;a<2;++a)
    for (int b=0;b<2;++b)
    for (int c=0;c<2;++c)
    for (int d=0;d<2;++d)
    if (((((a&b)^c))|d)==i) ++w[i];
    for (scanf("%d",&t);t;--t)
    {
        scanf("%d%d",&n,&k); long long ans=1;
        for (i=0;i<k;++i) ans*=w[(n>>i)&1];
        printf("%lld\n",ans);
    }
    return 0;
}

数位的关系

最后时间不够了我到比赛结束才看到这个题,感觉就是个比较显然的数位 DP

但这玩意之前都是交给徐神写的,而且感觉细节有点多不想补了,先坑着再说


众数

最神秘的一个题,赛时只想到了利用随机生成的性质得到的笛卡尔树是趋于平衡的,没想到可以直接利用这个性质求答案

注意到随机情况下答案极大概率是大数,因此直接把前 \(K=25\) 大的数拉出来算一下出现次数大概率就能得到答案

具体实现时可以用堆维护区间,每次取出最大值最大的区间 \([l,r]\) 后根据最大值所在的位置 \(p\) 分裂区间即可,最大值 \(a_p\) 的贡献即为 \((p-l+1)\times (r-p+1)\)

复杂度 \(O(nK\log n)\),代码十分好写

#include<cstdio>
#include<iostream>
#include<queue>
#include<utility>
#define int long long
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef pair <int,int> pi;
const int N=200005,K=25;
int t,n,q,a[N],l,r;
namespace RMQ
{
	pi mx[N][20]; int _log[N];
	inline void init(CI n)
	{
		RI i,j; for (_log[0]=-1,i=1;i<=n;++i)
		_log[i]=_log[i>>1]+1,mx[i][0]=pi(a[i],i);
		for (j=1;(1<<j)<=n;++j)
		for (i=1;i+(1<<j)-1<=n;++i)
		mx[i][j]=max(mx[i][j-1],mx[i+(1<<j-1)][j-1]);
	}
	inline pi query(CI l,CI r)
	{
		int k=_log[r-l+1]; return max(mx[l][k],mx[r-(1<<k)+1][k]);
	}
}
using namespace RMQ;
signed main()
{
	for (scanf("%lld",&t);t;--t)
	{
		RI i,j; for (scanf("%lld%lld",&n,&q),i=1;i<=n;++i) scanf("%lld",&a[i]);
		int ans=0; for (init(n),i=1;i<=q;++i)
		{
			scanf("%lld%lld",&l,&r); pi ret=pi(0,0);
			priority_queue <pair <pi,pi>> hp;
			hp.push(mp(query(l,r),pi(l,r)));
			for (j=1;j<=K&&!hp.empty();++j)
			{
				int val=hp.top().fi.fi,cnt=0;
				while (!hp.empty()&&hp.top().fi.fi==val)
				{
					auto [l,r]=hp.top().se; int p=hp.top().fi.se;
					cnt+=(p-l+1)*(r-p+1); hp.pop();
					if (l<=p-1) hp.push(mp(query(l,p-1),pi(l,p-1)));
					if (p+1<=r) hp.push(mp(query(p+1,r),pi(p+1,r)));
				}
				ret=max(ret,pi(cnt,val));
			}
			//printf("%lld = (%lld,%lld)\n",i,ret.fi,ret.se);
			ans^=i*ret.se;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

树上的 mex

防 AK 题,鉴定为弃疗


前面祁神去写了线段树扫描线维护矩形面积并的做法,但这样难以维护贡献而且时间复杂度也多个 \(\log\),后面我看了眼后发现可以直接离线用二维前缀和做

考虑将横纵坐标离散化,利用二位前缀和可以快速求出每个区域被多少个矩形覆盖了,并令 \(g_t\) 表示被 \(t\) 个矩形覆盖的面积

最后枚举选出的矩形数量 \(k\),则被覆盖的面积并(即至少覆盖一次的面积)的期望为:

\[\sum_{t=1}^n (1-\frac{C_{n-t}^k}{C_{n}^k})\times g_t \]

复杂度 \(O(n^2)\)

#include<bits/stdc++.h>
using namespace std;
#define int long long

const int MOD = 998244353, inv2 = 499122177;
const int mod = MOD;
const int INF = (int)1e18+5;
void add(int &x, int a){if ((x+=a)>=MOD) x-=MOD;}
int powe(int x, int p){
    int res=1;
    while (p>0){if (p&1) res=res*x%MOD; x=x*x%MOD; p>>=1;}
    return res;
}

const int N = 4005;
int fac[N], invf[N];
int n, mp[N][N];
int area[N];
vector<int> hshx, hshy;
struct Node{
    int x1, y1, x2, y2;
}nd[N];

signed main(){
    ios::sync_with_stdio(0); cin.tie(0);
    fac[0]=fac[1]=invf[0]=invf[1]=1;
    for (int i=2; i<N; ++i) fac[i]=fac[i-1]*i%MOD;
    invf[N-1] = powe(fac[N-1], MOD-2);
    for (int i=N-1; i>2; --i) invf[i-1]=invf[i]*i%MOD;

    cin >> n;
    hshx.push_back(-1); hshy.push_back(-1);
    for (int i=0; i<n; ++i){
        int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2;
        nd[i] = Node{x1, y1, x2, y2};
        hshx.push_back(x1), hshy.push_back(y1);
        hshx.push_back(x2), hshy.push_back(y2);
    }
    sort(hshx.begin(), hshx.end()); hshx.erase(unique(hshx.begin(), hshx.end()), hshx.end());
    sort(hshy.begin(), hshy.end()); hshy.erase(unique(hshy.begin(), hshy.end()), hshy.end());

    for (int i=0; i<n; ++i){
        int xx1 = lower_bound(hshx.begin(), hshx.end(), nd[i].x1) - hshx.begin();
        int xx2 = lower_bound(hshx.begin(), hshx.end(), nd[i].x2) - hshx.begin();
        int yy1 = lower_bound(hshy.begin(), hshy.end(), nd[i].y1) - hshy.begin();
        int yy2 = lower_bound(hshy.begin(), hshy.end(), nd[i].y2) - hshy.begin();
        mp[xx1][yy1]++; mp[xx1][yy2]--;
        mp[xx2][yy1]--; mp[xx2][yy2]++;
    }

    int szx=hshx.size(), szy=hshy.size();

    for (int i=1; i<szx; ++i){
        for (int j=1; j<szy; ++j){
            mp[i][j] = mp[i][j] + mp[i-1][j] + mp[i][j-1] - mp[i-1][j-1];
            add(area[mp[i][j]], (hshx[i+1]-hshx[i])*(hshy[j+1]-hshy[j])%MOD);
        }
    }


    for (int k=1; k<=n; ++k){
        int ans=0;
        for (int t=1; t<=n; ++t){
            if (n-t-k>=0) add(ans, area[t]*(MOD+1 - fac[n-t]*invf[n-t-k]%MOD*fac[n-k]%MOD*invf[n]%MOD)%MOD);
            else add(ans, area[t]);
        }
        cout << ans << '\n';
    }

    return 0;
}

Postscript

感觉这场好多数据结构啊,但还是打的一坨,下次遇到一堆计数的不是更加要被打出屎来

标签:钉耙,CI,now,const,int,编程,2024,include,define
From: https://www.cnblogs.com/cjjsb/p/18312365

相关文章

  • 学习Java的第五天(2024.7.18)
    1.字符串类:String类String类:是引用类型,默认值为null(注意不是空串"")字符串的声明:publicstaticvoidmain(String[]args){//声明字符串Stringstr="abc你好";System.out.println(str);str=newString("");//和strnewString();输出结果都......
  • 学习Java的第六天(2024.7.19)
    1.容器类、集合类之前学过的容器:数组,但是数组有局限:1.数组存储的数据类型有限制2.数组存储的长度受限2.容器类分为:List,Set,Map3.List类:List是一个接口,他的实现类有:ArrayList,LinkedList,Vectorpublicstaticvoidmain(String[]args){Listlist=newArrayLi......
  • 即将被淘汰 这几门编程语言!
    又到了周五了,忙碌了一周,可以放松放松一下了!在科技迅速发展的今天,编程语言的更新迭代速度令人惊叹。从经典的C语言到现代的Python,编程语言不断进化,满足着不同领域的需求。然而,有些编程语言却逐渐淡出我们的视野。你是否好奇,哪些编程语言即将被淘汰? 哪些编程语言正面临被淘汰......
  • SOLA4012 2024 Commercial PV
    SOLA40122024CommercialPVproject1 Scope summaryYouarea graduateengineerinalargeengineeringdepartmentof a well-knownPVinstaller (SPREEnergy).Thecompanyhasreceivedatenderrequestfromalargeretailer,fortheinstallation ofa non......
  • 2024.7 做题记录 2 / 顾影自怜了几回 直到看见妄自蕤
    CF653E不难发现其实就是在假想中建立出可以存在的边的图,要求跟\(1\)相连的连通块个数\(\leqk\)且与\(1\)的连边个数\(\geqk\)且全图联通,这个我们只需要知道其去掉\(1\)的连通性就很好讨论了。我们其实不能直接建出这个极度稠密的图,但是我们可以用数据结构优化建图,......
  • Python多任务编程的三种方式
    计算机的设计就是为了帮助人类或者模仿人类的某些行为。生活中的多任务:人可以一边唱歌,一边跳舞;人开车的时候是通过手、脚和眼睛共同配合来驾驶一辆车。多任务编程就是这样一个鲜明的例子,计算机也可以实现多任务编程:比如一边听歌一边玩游戏、打开浏览器上网同时能登录微信、QQ......
  • 2024牛客暑期多校训练营1 解题报告
    A-ABitCommon通过该题的性质可以知道偶数的关系不影响能够成立的序列我们只讨论最后一位为1的数这些数才能对该序列造成影响又因为对于每个特殊序列中每位必定有一个0所以特殊序列的个数为C(n,k)*2((m-1)*(m-n))*(2(m-1)-1)^(n-k)点击查看代码#include<bits/stdc++.h>......
  • 20240719数据库关联查询、条件查询
    mysql关联外键查询商品表和图片表是分开的,用一张商品图片表关联起来了。查询商品表所有字段和图片信息。其余的,商人id、区域id、分类id都是直接关联,没有中间表SELECTp.id,p.name,p.price,p.unit,f.file,p.description,p.is_on_sale,p.......
  • Java中的多线程编程与锁机制解析
    Java中的多线程编程与锁机制解析大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!今天,我们将深入探讨Java中的多线程编程与锁机制。多线程编程在现代应用开发中至关重要,它允许程序同时执行多个任务,从而提高程序的响应性和性能。我们将通过代码示例来解析Jav......
  • Java中的动态代理与AOP编程
    Java中的动态代理与AOP编程大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!今天我们将探讨Java中的动态代理和面向切面编程(AOP),这两者是构建灵活且可扩展系统的重要工具。1.动态代理概述在Java中,动态代理允许我们在运行时创建代理对象,从而可以在不修改现......