• bzoj4415&&bzoj4416&&bzoj4417:SHOI2013Day1题解


    这场题好弱啊qwq

    先发代码再填坑

    坑已填qwq

    T1 bzoj4415

    题目大意就是,有一个环,编号1-N,一开始指针在1,有一个长度为n的序列p,每次指针向后移pi个,然后把那个点删掉。

    问所有点被删掉的顺序

    然后用树状数组维护每个点有没有被删掉,然后就可以通过树状数组上二分求出每次删除的位置。然后就做完了

    (以前不会树状数组上二分啊...一直写的log^2的二分...不过稍微YY一下就会了)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    #define N 700005
    
    using namespace std;
    inline int read(){
    	int ret=0;char ch=getchar();
    	while (ch<'0'||ch>'9') ch=getchar();
    	while ('0'<=ch&&ch<='9'){
    		ret=ret*10-48+ch;
    		ch=getchar();
    	}
    	return ret;
    }
    
    int n;
    struct BIT{
    	int c[N];
    	int lowbit(int x){return x&-x;}
    	void load(){
    		memset(c,0,sizeof(c));
    		for (int i=1;i<=n;++i){
    			++c[i];
    			if (i+lowbit(i)<=n) c[i+lowbit(i)]+=c[i];
    		}
    	}
    	int solve(int sum){
    		int x=0,now=0;
    		for (int i=(1<<20);i;i=i>>1)
    			if (x+i<=n&&now+c[x+i]<sum){
    				x+=i;now+=c[x];
    			}
    		for (int i=(++x);i<=n;i+=lowbit(i)) --c[i];
    		return x;
    	}
    } bit;
    
    
    int main(){
    	n=read();
    	bit.load();
    	int now=n,sum=n;
    	for (int i=n;i;--i){
    		int x=read()%i+1;
    		if (i-sum>=x) sum=sum+x-1;
    		else sum=x+sum-i-1;
    		printf("%d
    ",bit.solve(sum+1));
    	}
    	return 0;
    }
    

    T2 bzoj4416

    题目大意是,给你一个字符串,长度l<=450,由n<=26个字母组成,要你判断  所有n个字母的排列是否都是这个给定串的子串(可以不连续)

    Claris好神啊!

    首先预处理出next[i][x]表示第i位之后最近的字母x的位置(不存在就l+1),然后dp[mask]表示集合为mask最早被全员匹配的位置,然后枚举最后出现的字母进行转移。

    然后就做完了,dp[全1状态]<=l就是yes

    啊..对..还有一个特判,就是我们可以发现满足要求的串最短是n^2级别的,所以如果n>21直接输出NO

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #define N 30
    #define L 505
    
    using namespace std;
    int n,l;char s[L];
    int nxt[L][N],dp[1<<21^233];
    
    inline int lowbit(int x){return x&-x;}
    
    bool work(){
    	scanf("%d%s",&n,s+1);l=strlen(s+1);
    	if (n>21) return 0;
    	for (int i=0;i<n;++i) nxt[l+1][i]=l+1;
    	for (int i=l;i>=0;--i){
    		for (int j=0;j<n;++j) nxt[i][j]=nxt[i+1][j];
    		if (i) nxt[i][s[i]-'a']=i;
    	}
    	for (int i=dp[0]=0;i<(1<<n);dp[++i]=0)
    		for (int j=0;j<n;++j)if ((i&(1<<j))>0)
    			dp[i]=max(dp[i],nxt[dp[i^(1<<j)]][j]);
    	return dp[(1<<n)-1]<=l;
    }
    
    int main(){
    	int testnumber;scanf("%d",&testnumber);
    	while (testnumber--) puts(work()?"YES":"NO");
    	return 0;
    }
    

    T3 bzoj4417

    傻逼矩阵乘法,n*2个状态表示跳奇数&偶数次每行的方案数,然后有2个转移矩阵一个是奇to偶另一个是偶to奇,随便YY一下快速幂就行了。

    然而发现我的代码长度运行时间还有内存都是其他人的3倍左右QAQ一定是我傻逼了TAT

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #define ll long long
    #define P 30011 
    
    using namespace std;
    
    struct matrix{
    	int x,y;
    	int a[105][105];
    	matrix(){}
    	matrix(int _x,int _y):x(_x),y(_y){}
    	matrix(int _x){
    		x=y=_x;
    		memset(a,0,sizeof(a));
    		for (int i=1;i<=_x;++i) a[i][i]=1;
    	}
    } A,B,C,D;
    
    inline matrix operator *(matrix a,matrix b){
    	if (a.y!=b.x) swap(a,b);
    	matrix ret=matrix(a.x,b.y);
    	int z=a.y;
    	for (int i=1;i<=ret.x;++i)
    		for (int j=1;j<=ret.y;++j){
    			ret.a[i][j]=0;
    			for (int k=1;k<=z;++k)
    				(ret.a[i][j]+=(ll)a.a[i][k]*b.a[k][j]%P)%=P;
    		}
    	return ret;
    }
    
    matrix pow(matrix x,int y){
    	matrix ret=matrix(x.x);
    	while (y){
    		if (y&1) ret=ret*x;
    		y/=2;
    		x=x*x;
    	}
    	return ret;
    }
    
    
    int main(){
    	int n,m;scanf("%d%d",&n,&m);
    	if ((--m)==1){printf("%d
    ",n<=2);return 0;}
    	A=matrix(2*n);B=matrix(2*n);
    	for (int i=1;i<=n;++i)
    		for (int j=max(i-1,1);j<=i+1&&j<=n;++j)
    			++A.a[j][i+n],++B.a[j+n][i];
    	int ans=0;
    	if (m&1){
    		C=A*B;
    		D=B*pow(C,m/2-1);
    		ans=D.a[2*n][1];
    		D=D*C;
    		ans=(D.a[2*n][1]-ans+P)%P;
    	}
    	else{
    		C=A*B;
    		D=pow(C,m/2-1);
    		ans=D.a[n][1];
    		D=D*C;
    		ans=(D.a[n][1]-ans+P)%P;
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    Runtime源码解析(JDK1.8)
    剑指Offer-孩子们的游戏(圆圈中最后剩下的数)
    剑指Offer-把二叉树打印成多行
    剑指Offer-按之字形顺序打印二叉树
    剑指Offer-对称的二叉树
    剑指Offer-删除链表中重复的结点
    剑指Offer-链表中环的入口结点
    剑指Offer-字符流中第一个不重复的字符
    剑指Offer-构建乘积数组
    selenium获取微博用户粉丝数
  • 原文地址:https://www.cnblogs.com/wangyurzee7/p/5252312.html
Copyright © 2020-2023  润新知