qbxt Day 6

Day 6

考试题解

T1 math

签到成功,开心。

看到\(T1\)第一反应,这啥呀???又考数论???先打暴力先打暴力。什么???暴力都过不了,连暴力都打不出来吗???完了完了,签到题不会爆0吧。冷静地分析一波之后,我盲猜这绝对是个结论题,需要推导证明。但考虑到这是签到题,我决定不浪费时间去证明。再次赌神附体,口胡结论,暴力对拍后验证结论后签到成功。题解证明数学结论,然而没听懂,还是不会。

其实暴力打表上几组数据很容易发现规律,实际上就是将指数的最大公因数作为指数,用一个快速幂取模运算求出答案即可。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
ll ksm(ll a1,ll x1,ll p1){
	ll ans=1;
	while(x1){
		if(x1&1) ans=(ans*a1)%p1;
		a1=(a1*a1)%p1;
		x1>>=1;
	}
	return ans;
}
ll gcd(ll a,ll b){
	if(b==0){
		return a;
	}
	return gcd(b,a%b);
}
ll T,q,a,b,p;
int main()
{ 
	scanf("%lld",&T);
	while(T--){
		scanf("%lld%lld%lld%lld",&q,&a,&b,&p);
		printf("%lld\n",(ksm(q,gcd(a,b),p)-1+p)%p);
	}
	return 0;
}

T2 candy

100分做法:

这个\(A\)\(B\)的数据范围都在1e6以内,暗示选手开桶做。但是我只注意到了单调性,而忘记了使用桶维护,最终还是没能切掉\(T2\)

当前弧优化的思想。对于一个A,它找到的B是A的倍数,而且是单调的,所以不需要重新扫描。这样复杂度就是调和级数。总时间复杂度O(nlogn)。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
int n,m,tot; 
int a[1000005],b[1000005],cnt[1000005],t[1000005],f[1000005];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&b[i]);
		cnt[b[i]]++;
	}
	scanf("%d",&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		f[a[i]]=a[i];
	}
	for(int i=1;i<=n;i++){
		int p=f[a[i]];
		while(p<=1e6&&!cnt[p]) p+=a[i];
		if(p>1e6){
			printf("%d\n",tot);
			for(int j=1;j<=tot;j++){
				printf("%d ",t[j]);
			}
			printf("\n");
			return 0;
		}
		tot++;
		t[tot]=p;
		f[a[i]]=p;
		cnt[p]--;
	}
	return 0;
}

T3 lagrange

结论:

拉格朗日恒等式:sigma a_i^2 * sigma b_i^2 = sigma (a_i*b_i)^2 + sigma(a_ib_j-a_jb_i)

其实不知道结论也能做,随便代入1~3算出结果然后找规律即可,用线段树或树状数组维护即可写出正解。总时间复杂度\(O((n+m)logn)\)

代码还没调出来QWQ,不知道哪里有问题

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
inline ll read(){
	ll x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
const ll mod=998244353;
ll n,m;
ll a[5000005],b[5000005];
struct Node{
	ll v1,v2,v3,v4,v5,tag1,tag2;
	int l,r;
	Node *ls,*rs;
	Node(const int L,const int R){
		l=L,r=R;
		if(l==r){
			tag1=0;
			tag2=0;
			v1=a[l]*a[l]%mod;//A序列平方和
			v2=b[l]*b[l]%mod;//B序列平方和
			v3=a[l]*b[l]%mod;//A序列和B序列对应相乘
			v4=a[l];//A序列和
			v5=b[l];//B序列和
			ls=NULL;
			rs=NULL;
		}
		else{
			tag1=0;
			tag2=0;
			int M=(L+R)/2;
			ls=new Node(L,M);
			rs=new Node(M+1,R);
			pushup();
		}
	}
	inline void pushup(){
		v1=(ls->v1+rs->v1)%mod;
		v2=(ls->v2+rs->v2)%mod;
		v3=(ls->v3+rs->v3)%mod;
		v4=(ls->v4+rs->v4)%mod;
		v5=(ls->v5+rs->v5)%mod;
	}
	inline void pushdown(){
		if(tag1==0&&tag2==0) return;
		else{
			ls->maketag(tag1,tag2);
			rs->maketag(tag1,tag2);
			tag1=0;
			tag2=0;
		}
	}
	inline void maketag(ll w1,ll w2){
		tag1=(tag1+w1)%mod;
		tag2=(tag2+w2)%mod;
		v3=(v3+v4*w2%mod+v5*w1%mod+(r-l+1)*w1%mod*w2%mod)%mod;
		v1=(v1+(r-l+1)*w1%mod*w1%mod+2*w1%mod*v4%mod)%mod;
		v2=(v2+(r-l+1)*w2%mod*w2%mod+2*w2%mod*v5%mod)%mod;
		v4=(v4+(r-l+1)*w1%mod)%mod;
		v5=(v5+(r-l+1)*w2%mod)%mod;//通过公式分别更新,要注意顺序
	}
	inline bool InRange(const int L,const int R){
		return (l>=L)&&(r<=R);
	}
	inline bool OutofRange(const int L,const int R){
		return (l>R)||(r<L);
	}
	inline void upd(const int L,const int R,ll w1,ll w2){
		if(InRange(L,R)){
			maketag(w1,w2);
		}
		else if(!OutofRange(L,R)){
			pushdown();
			ls->upd(L,R,w1,w2);
			rs->upd(L,R,w1,w2);
			pushup();
		}
	}
	inline ll qry(const int L,const int R){
		if(InRange(L,R)){
			return ((v1*v2)%mod+mod-v3*v3%mod+mod)%mod;
		}
		if(OutofRange(L,R)){
			return 0;
		}
		else{
			pushdown();
			return (ls->qry(L,R)+rs->qry(L,R))%mod;
		}
	}
};
int main()
{
	n=read();
	m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	for(int i=1;i<=n;i++){
		b[i]=read();
	}
	Node *rot=new Node(1,n);
	while(m--){
		ll op,x,y,z;
		op=read();
		x=read();
		y=read();
		if(op==1){
			printf("%lld\n",rot->qry(x,y)%mod);
		}
		else{
			z=read();
			rot->upd(x,x,y-a[x],z-b[x]);
			a[x]=y;
			b[x]=z;//奇技淫巧实现单点覆盖,不知道对不对,自己测好像没问题
		}
	}
	return 0;
}

T4 loop

状压dp?

??????????????????

贪心

没有什么通用技巧,靠感觉做题。猜结论之后对拍证明。

贪心乱搞

求有向图尽量长的简单路径(注意不是最长)。保证存在哈密顿路。N<=100000

?????????????????

匈牙利->一般图最大匹配

DAG和CPU

?????????????????

IOI2020热身赛

?????????????????

Kruskal

CF875F

最大生成环套树森林,因为两个点取一个点的权值,所以如果围成一个环的话那么就正好取完所有点,然后在合并的时候,不能将两个环套树合并,只能将两个树合并或者是一个树和一个环套树合并。

CF1239B

左括号+1,右括号-1,首先手动交换换成合法答案,画成折线图,然后在保证序列合法的前提下,将纵坐标大于2的点之间左右括号交换,相当于-2,出现0点则恰好匹配。

CF1381D

有三个长度大于等于蛇的长度的不同的子树。然后在a->b上的链上不停蠕动,直到找到符合条件的子树。

v=1的情况。称花的根为最上面那个点,当v=1时,从下往上贪心即可,能选就选。

????????????????????

黑题

????????????????????

????????????????????

模拟

好题(bushi):猪国杀,杀蚂蚁

代码能力很重要,调试能力就相当于是推断。

CF1025E

先把棋子移到对角线上,????????????

CF1320F

构造出符合条件的长方体。

二分

二进制分组

比二分更加优秀和优美。

整体二分

??????????????????

二分斜率

??????????????????

入门题

二分答案,前缀和后逆序对????????????????????????

经典题

?????????????????????

CF607E

????????????????????????

后面的题全部炸裂,老师错误的估计了我们的水平,没有考虑到我们这些菜鸡的存在,题目找得过难了,就只有一小部分巨神还能跟上老师思路,最炸裂的一天

posted @ 2020-10-06 23:46  徐明拯  阅读(126)  评论(0编辑  收藏  举报