模拟测试(vj3)

今天写题的过程中,发现我太菜了,写出来的T2 还是靠 py 的。。

今天的题目顺序有点小坑,第一题是难度最大的一题!很多同学都和我一样硬钢,然后时间就这样逝去的。

从难度大的开始分析吧。

T5.dp+矩阵快速幂。

我们设d[i]为以d[i]为深度的满足条件的点,也就是答案。

可以得出d[i]=

 

这个是很显然的,因为每一个点都可以转化为其他点到达。

但是看数据的范围,知道这样肯定会T掉,于是我们就需要矩阵快速幂的优化。怎么优化呢?我讲不清楚,于是就截了一张大神的图,orz~

 

 

 

我来分析一下吧,B数组的若干个10,其实是取到保留位的作用,因为只有1出现的位置,才对A数组有功效。其实他的图并不全,因为我们要加上根节点的1,所以我们还要开辟一列,在b[101][1],b[101][101]设为1,这样才会保留1,才能进行矩阵幂。

说一下代码实现的细节吧,矩阵快速幂模板一写,然后要注意边界的问题,我们要用两个变量分别记录a,b数组的边界,然后跑*运算不要越界就可以了。

 

T4.线段树+二分

我们建造5颗维护最值的线段树,然后二分区间的长度,枚举起点,注意不要越界,然后就可以轻松解决了,但是我是线段树小白,发现线段树都不会写,折磨了好久。。以后还要学学。(老师说了一种运用单调队列的方法,orz

T3.哈希 就是修改一个字符串的每个节点,因为只有abc三个字符,枚举一遍。然后判断有没有重复。

T2.暴力出奇迹,比较任意两个点,算k。我写了另一种nlogn的算法,但是由于精度的问题,炸了。。

T1.就是模拟吧,判断每一个位上的字符和9-该位的字符的大小,然后就可以出来了。

PS:另更新一文为矩阵快速幂模板。

附上代码:

A

 

#include<bits/stdc++.h>
#define maxn 120
#define mod (1000000007)
#define LL long long
using namespace std;
LL n,k;
struct Node{
    LL s[maxn][maxn];
    int n,m;
}str;

Node operator * (Node a,Node b)
    {
        Node tmp;tmp.n=a.n;tmp.m=b.m;
        LL x=0;
        for(int i=1;i<=a.n;i++)
            for(int j=1;j<=b.m;j++)
            {
                x=0;
                for(int k=1;k<=a.m;k++)
                    x+=a.s[i][k]*b.s[k][j]%mod;
                tmp.s[i][j]=x%mod;
            }
        return tmp;
    }
int main()
{
    cin>>n>>k;
    Node a,b;a.n=1,a.m=101;b.n=b.m=101;
    b.s[101][1]=b.s[101][101]=1;
    a.s[1][1]=a.s[1][101]=1;
	for(int i=2;i<=100;i++) b.s[i-1][i]=1;
	for(int i=1;i<=n;i++)
	{
		int kk;
    	cin>>kk;b.s[kk][1]++;
    }
        while(k)
        {
            if(k&1) a=a*b;
            b=b*b;
            k>>=1;
        }
    cout<<a.s[1][1]<<endl;
    return 0;
}

 

 C

#include<bits/stdc++.h>
#define ls (rt<<1)
#define rs (rt<<1|1)
#define maxn 500000
#define inf 12984020
using namespace std;
int n,m,k;

struct IntervalTree{
	int Max[maxn];
	int a[maxn];
	void build(int l,int r,int rt)
	{
		if(l==r) {Max[rt]=a[l];return;}
		int mid=l+(r-l)/2;
		build(l,mid,ls),build(mid+1,r,rs);
		Max[rt]=max(Max[ls],Max[rs]);
	}

	int query(int L,int R,int l,int r,int rt)
	{
		int amax=0;	
		if(L<=l&&r<=R) {amax=max(amax,Max[rt]);return amax;}
		else 
		{
			int lmax=0,rmax=0;
			int mid=l+(r-l)/2;
			if(L<=mid)lmax=max(lmax,query(L,R,l,mid,ls));
			if(R>mid) rmax=max(rmax,query(L,R,mid+1,r,rs));
			return amax=max(lmax,rmax);
		}
	}
	
	void output(int l,int r,int rt)
	{
		if(l==r) return ;
		cout<<l<<" "<<r<<" "<<Max[rt]<<endl;
		int mid=l+(r-l)/2;
		output(l,mid,ls),output(mid+1,r,rs);

	}
	
}tree[8];

int sum[8],rans[8];

int erfen(int x)
{
	if(x==0) return 1;
	for(int i=1;i<=n-x+1;i++)
	{
		memset(sum,0,sizeof(sum));
		int ans=0;
		for(int j=1;j<=m;j++)
		{
			sum[j]=tree[j].query(i,i+x-1,1,n,1);
			ans+=sum[j];
		}
		if(ans<=k)
		{
			for(int i=1;i<=m;i++)
				rans[i]=sum[i];
			return 1;
		}
	}
	return 0;
}

int main()
{
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			cin>>tree[j].a[i];
	for(int i=1;i<=m;i++)
		tree[i].build(1,n,1);
	int l=1,r=n;
	while(l<=r)
	{
			int mid=l+(r-l)/2;
			if(erfen(mid)) 
				l=mid+1;
			else r=mid-1;
	}
	for(int i=1;i<=m;i++)
		cout<<rans[i]<<" ";
	return 0;
	
}

 这种结构体内套线段树真的好用!

E

#include<bits/stdc++.h>
#define mod 1000000000000000007
#define LL long long
using namespace std;
LL se[600100];
LL n,m;
set<LL> s;
inline LL hash(string str)
{
	LL len=str.length();
	LL ha=0;
	for(LL i=0;i<len;i++)
		ha+=(se[i]*(str[i]-'a'+1)%mod)%mod,ha%=mod;
	return ha;
}

inline bool judge(string str)
{
	LL ha=hash(str);
	LL len=str.length();
	for(LL j=0;j<len;j++)
	{
		LL num=str[j]-'a'+01;
		for(LL i=1;i<=3;i++) if(i!=num)
		{
			LL haah=(ha-(num*se[j])%mod+(i*se[j])%mod+mod)%mod;
			if(s.count(haah))
				return 1;
		}
	}
	return 0;
}

int main()
{
	se[0]=1;
	for(LL i=1;i<=600006;i++)
		se[i]=(se[i-1]*4)%mod;
	s.clear();
	string str;
	cin>>n>>m;
	for(LL i=1;i<=n;i++)
	{cin>>str;s.insert(hash(str));}
	for(LL i=1;i<=m;i++)
	{
		cin>>str;
		if(judge(str))
			cout<<"YES\n";
		else cout<<"NO\n";
	}
	return 0;
}

 D

#include<bits/stdc++.h>
#define  maxn 2000
#define mod (1000000000+7)
using namespace std;
int n,k;
double sx,sy;
double x[maxn],y[maxn];
int book[maxn];
int ans=0;

int main()
{
	cin>>n>>sx>>sy;
	for(int i=1;i<=n;i++)
		cin>>x[i]>>y[i];
	for(int i=1;i<=n;i++)if(!book[i])
	{
		book[i]=1;ans++;
		for(int j=i+1;j<=n;j++)
		{
			if(x[i]==sx&&x[j]==sx) book[j]=1;
			else if((y[i]-sy)/(x[i]-sx)==(y[j]-sy)/(x[j]-sx)) book[j]=1;
		}
	}
	cout<<ans<<endl;
	return 0;
}
/*
4 0 0
10000 9999
9999 9998
-10000 -9999
-9999 -9998
*/

 下面是我yy出来的坑数据

B

#include<bits/stdc++.h>
using namespace std;
long long n;
int s[2000];
int cnt=0;
int main()
{
	cin>>n;
	while(n>=1)
		s[++cnt]=n%10,n/=10;
	if(s[cnt]==9) cout<<'9';
	else cout<<min(s[cnt],9-s[cnt]);
	for(int i=cnt-1;i>=1;i--)
		cout<<min(s[i],9-s[i]);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值