模拟测试(vj3)

来源:互联网 发布:什么叫品牌战略 知乎 编辑:程序博客网 时间:2024/06/05 04:23
今天写题的过程中,发现我太菜了,写出来的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 longusing 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 12984020using 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 longusing 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 010000 99999999 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;}