• [省选集训2022] 模拟赛18


    题目描述

    给定两边各 \(n\) 个点的二分图,在这张图中,左边的 \(i\) 号点向右边的 \(1,2,3...a_i\) 号点连边。请你求出图中的简单环个数,答案对 \(998244353\) 取模,定义两个环不同为存在一条边在一个环出现了但是在另一个中不出现。

    \(1\leq n\leq 5000,1\leq a_i\leq n\)

    解法

    首先可以把 \(a_i\) 从小到大排序,发现这样并不会改变答案而且简化了问题。

    没有什么其他的性质了,直接考虑 \(dp\) 吧。考虑每次增量一个左部的点,然后考虑它连出去的两条边,达到的效果就是合并两条路径

    所以我们可以记录路径个数,为了简化计算我们定义路径为有向路径。设 \(dp[i][j]\) 表示考虑前 \(i\) 个左部点,形成的有向路径数量是 \(j\) 个。转移可以分两部,第一步是添加 \(a_i-a_{i-1}\) 个右部单点:

    \[dp[i][j]\leftarrow \sum_{k=0}^{a_i-a_{i-1}} dp[i-1][j-k]\cdot {a_i-a_{i-1}\choose k} \]

    第二步是任取两条有向路径合并:

    \[dp[i][j]\leftarrow dp[i][j+1]\cdot j\cdot (j+1) \]

    时间复杂度 \(O(n^2)\),我们在第一步转移之后将 \(dp[i][1]\) 计入答案。

    总结

    不要纠结于神奇性质,有时候可以直接规划。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int M = 5005;
    const int MOD = 998244353;
    #define int long long
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,ans,a[M],C[M][M],dp[M][M];
    void add(int &x,int y) {x=(x+y)%MOD;}
    signed main()
    {
    	freopen("ring.in","r",stdin);
    	freopen("ring.out","w",stdout);
    	n=read();
    	for(int i=0;i<=n;i++)
    	{
    		C[i][0]=1;
    		for(int j=1;j<=i;j++)
    			C[i][j]=(C[i-1][j-1]+C[i-1][j])%MOD;
    	}
    	for(int i=1;i<=n;i++) a[i]=read();
    	sort(a+1,a+1+n);dp[0][0]=1;
    	for(int i=1;i<=n;i++)
    	{
    		int d=a[i]-a[i-1];
    		for(int j=0;j<=a[i];j++)
    			for(int k=max(0ll,j-d);k<=j;k++)
    				add(dp[i][j],dp[i-1][k]*C[d][j-k]);
    		add(ans,dp[i][1]-a[i]+MOD);
    		for(int j=0;j<=a[i];j++)
    			add(dp[i][j],dp[i][j+1]*j%MOD*(j+1));
    	}
    	printf("%lld\n",ans*((MOD+1)/2)%MOD);
    }
    

    题目描述

    给定正整数 \(n\),问有多少正整数 \(1\leq k\leq n\) 满足:使得 \(a^2+b^2=k+c^2\) 的正整数 \(a,b,c\) 有唯一解。

    \(n\leq 10^{11}\)

    解法

    通过打表发现,当 \(k\bmod 4=1/2\) 时,一组解都没有,我们可以在这个结论的基础上进一步分析。

    \(c=2b-a\) 带入,整理得到 \(k=b(3b-4a)\),那么合法的 \((a,b,c)\) 对应 \(k\) 的一个分解 \(k=xy\),且满足 \(x+y=0\bmod 4\)\(3x>y\)

    \(k\) 写成 \(u\cdot 2^{v}\) 的形式,那么当 \(v=0\) 时,只有当 \(u\bmod 4=3\) 才存在解,并且 \(u\) 是质数才存在唯一解(要不然有多种分配方式);当 \(v>0\) 时,只有 \(v=2/4\) 并且 \(u\) 时质数才有唯一的分解方式。

    综上,满足条件的 \(k\) 当且仅当:\(k\) 为模 \(4\)\(3\) 的质数;\(k\)\(>2\) 的质数 \(\times 4\)\(k\)\(>2\) 的质数 \(\times 16\)\(k\)\(4\)\(k\)\(16\)

    既然是统计质数个数可以考虑用 \(\tt min\_25\) 筛,主要是怎么统计模 \(4\)\(3\) 的质数?我们可以把初始的数分为两类:模 \(4\)\(1\) 和 模 \(4\)\(3\);那么筛的时候考虑用来筛的质数模 \(4\) 余几,就可以转移了。

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    using namespace std;
    const int M = 2000005;
    #define int long long
    int read()
    {
    	int x=0,f=1;char c;
    	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
    	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    	return x*f;
    }
    int n,m,cnt,tot,w[M],p[M],vis[M],sp[M][2],g[M][2];
    int id1[M],id2[M];
    int get(int x)
    {
    	return x<=m?id1[x]:id2[n/x];
    }
    void init(int n)
    {
    	for(int i=2;i<=n;i++)
    	{
    		if(!vis[i])
    		{
    			p[++cnt]=i;
    			sp[cnt][0]=sp[cnt-1][0];
    			sp[cnt][1]=sp[cnt-1][1];
    			if(i>2) sp[cnt][i%4==3]++;
    		}
    		for(int j=1;j<=cnt && i*p[j]<=n;j++)
    		{
    			vis[i*p[j]]=1;
    			if(i%p[j]==0) break;
    		}
    	}
    }
    signed main()
    {
    	freopen("number.in","r",stdin);
    	freopen("number.out","w",stdout);
    	init(1e6);n=read();m=sqrt(n);
    	for(int l=1,r;l<=n;l=r+1)
    	{
    		r=n/(n/l);
    		w[++tot]=n/l;
    		g[tot][0]=w[tot]-1>>2;
    		g[tot][1]=w[tot]+1>>2;
    		if(n/l<=m) id1[n/l]=tot;
    		else id2[n/(n/l)]=tot;
    	}
    	for(int i=2;i<=cnt;i++)
    		for(int j=1;j<=tot && p[i]*p[i]<=w[j];j++)
    		{
    			int k=get(w[j]/p[i]),f=p[i]%4==3;
    			g[j][0]-=g[k][f]-sp[i-1][f];
    			g[j][1]-=g[k][f^1]-sp[i-1][f^1];
    		}
    	int ans=g[get(n)][1];
    	ans+=g[get(n/4)][0]+g[get(n/4)][1]+(n>=4);
    	ans+=g[get(n/16)][0]+g[get(n/16)][1]+(n>=16);
    	printf("%lld\n",ans);
    }
    
  • 相关阅读:
    python拆包与装包-*args,**kwargs
    mybatis学习4-CRUD操作
    mybatis学习3-入门案例,注解方式
    mybatis学习1-前置,复习Jdbc
    spring框架学习-aop
    spring学习1-第一个spring项目
    spring概述
    idea的一些个人设置
    maven的一些个人设置
    VBA文件对话框的应用(VBA打开文件、VBA选择文件、VBA选择文件夹,VBA遍历文件夹)
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/16083932.html
Copyright © 2020-2023  润新知