• 17.10.27


      • 上午
        • 模拟考试,(是真的绝望,555。全部记录吧)
        • Prob.1(WA)太神了,没想出正解,也没打暴力、、、

    image

    题解:

    image

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int mod=998244353;
    int ans,n,val=1;
    int pow(int a,int b){
    	int now=1;
    	while(b){
    		if(b&1) now=1ll*now*a%mod;
    		a=1ll*a*a%mod; b>>=1;
    	}
    	return now;
    }
    int main(){
    	freopen("A.in","r",stdin);
    	freopen("A.out","w",stdout);
    	scanf("%d",&n);
    	for(int i=1,x;i<=n;i++){
    		scanf("%d",&x);
    		val=1ll*val*x%mod;
    	}
    	val=pow(val,mod-2);
    	printf("%d",val);
    	return 0;
    }
    

    他们没看出这个模型的,但是通过小数据化简出来了这个式子了,

    我当时居然没有化简出来,好吧,是根本没化简,罪该万死、、、

        • Prob.2(WA4组)构造题,但没构造出来、、、

    image

    题解、、、

    image

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    char mp1[505][505],mp2[505][505],x;
    int n,m;
    int main(){
    	freopen("B.in","r",stdin);
    	freopen("B.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++){
    			scanf(" %c",&x);
    			if(x=='1') mp1[i][j]=mp2[i][j]='1';
    			else mp1[i][j]=mp2[i][j]='0';
    		}
    	for(int i=1;i<=n;i+=2)
    		for(int j=1;j<m;j++) mp1[i][j]='1';
    	for(int i=1;i<=n;i++) mp1[i][1]='1';
    	for(int i=2;i<=n;i+=2)
    		for(int j=2;j<=m;j++) mp2[i][j]='1';
    	for(int i=1;i<=n;i++) mp2[i][m]='1';
    	for(int i=1;i<=n;i++){ 
    		for(int j=1;j<=m;j++)
    			printf("%c",mp1[i][j]);
    		printf("
    ");
    	} 
    	printf("
    ");
    	for(int i=1;i<=n;i++){ 
    		for(int j=1;j<=m;j++)
    			printf("%c",mp2[i][j]);
    		printf("
    ");
    	}
    	return 0;
    }
    
          • Prob.3(WA6组)神dp,根本没看出来是个dp?!

    image

    题解:(神dp,%%%)

    image

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    char mp[105][105];
    short area[105][105],dp[105][105][105][105];
    short sx,sy,n,m,ans;
    short query(int x1,int y1,int x2,int y2){
    	if(x1>x2||y1>y2) return 0;
    	return area[x2][y2]+area[x1-1][y1-1]-area[x2][y1-1]-area[x1-1][y2];
    }
    int main(){
    	freopen("C.in", "r", stdin);
    	freopen("C.out", "w", stdout);
    	cin>>n>>m;
    	for(int i=1;i<=n;i++){
    		scanf("%s",mp[i]+1);
    		for(int j=1;j<=m;j++){
    			if(mp[i][j]=='E') sx=i,sy=j;
    			area[i][j]=area[i-1][j]+area[i][j-1]-area[i-1][j-1]+(mp[i][j]=='o');
    		}
    	}
    	short L=sy-1,R=m-sy,U=sx-1,D=n-sx;
    	for(int l=0;l<=L;l++)
    		for(int r=0;r<=R;r++)
    			for(int u=0;u<=U;u++)
    				for(int d=0;d<=D;d++){
    					ans=max(ans,dp[l][r][u][d]);
    					if(l+r<sy-1){
    						int x=sx-u,y=sx+d;
    						x=max(x,d+1); y=min(y,n-u);
    						dp[l+1][r][u][d]=max(dp[l+1][r][u][d],(short)(dp[l][r][u][d]+query(x,sy-l-1,y,sy-l-1)));
    					}
    					if(l+r<m-sy){
    						int x=sx-u,y=sx+d;
    						x=max(x,d+1); y=min(y,n-u);
    						dp[l][r+1][u][d]=max(dp[l][r+1][u][d],(short)(dp[l][r][u][d]+query(x,sy+r+1,y,sy+r+1)));
    					}
    					if(u+d<sx-1){
    						int x=sy-l,y=sy+r;
    						x=max(x,r+1); y=min(y,m-l);
    						dp[l][r][u+1][d]=max(dp[l][r][u+1][d],(short)(dp[l][r][u][d]+query(sx-u-1,x,sx-u-1,y)));
    					}
    					if(u+d<n-sx){
    						int x=sy-l,y=sy+r;
    						x=max(x,r+1); y=min(y,m-l);
    						dp[l][r][u][d+1]=max(dp[l][r][u][d+1],(short)(dp[l][r][u][d]+query(sx+d+1,x,sx+d+1,y)));
    					}
    				}
    	cout<<ans;
    	return 0;
    }
    
          • 下午
            • 改错ing、、、
            • BOZJ 1077 [SCOI2008]天平

    好题,差分约束 + 神判断。
    定义两个数组:(a[i]表示i号砝码的重量)
    dmax[i][j]:表示a[i]-a[j]最大为多少。(在判断时可以理解为使a[i]尽可能大,a[j]尽可能小)
    dmin[i][j]:表示a[i]-a[j]最小为多少。(在判断时可以理解为使a[i]尽可能小,a[j]尽可能大)
       
    按照读入数据,给两个数组赋上初值,然后两个floyd跑差分约束,得到正确的dmax数组和dmin数组
       
    判断:(N^2枚举 C,D)
    1). A + B > C + D:
        为保证结果唯一,
        我们想要使得等式左边(A + B)尽量小,等式右边(C + D)尽量大:
        表示为  A(小) + B(小) > C(大) + D(大)
        如果 左边任然满足大于右边,则第一类答案 ans1++;
           
        把式子化简为差值的形式,便于使用dmax和dmin数组
         =>  1)).A(小) - C(大) > D(大) - B(小)
                =>dmin[A][C] > dmax[D][B]
             2)).A(小) - D(大) > C(大) - B(小)
                =>dmin[A][D] > dmax[C][B]
        所以只要满足上面两个式子中的任意一个,就可以ans1++。
        if(dmin[A][C]>dmax[D][B]||dmin[A][D]>dmax[C][B]) ans1++;
            _____________________________________________________________________
         有一点需要注意:
             两个式子是可以相互化的,为什么需要判断两个?
             因为输入数据给出约束信息不一定完整,
             即我们可能计算出的信息满足第二个式子
             (即计算出 A与D的关系 和  C与B的关系 满足不等式),
             但是不一定满足第一个式子。
             (即不一定计算出了的 A与C的关系 和 B与D的关系)
             所以只要任意一个式子满足就好了。
         另外,还有一点需要细想一下:
             那既然想上面所说的那样,约束信息不一定完整,
             那为什么不判一判 A + B > C + D这个式子还可以化出的另外两个差值不等式呢?
             比如  B(小) - C(大) > D(大) - A(小)这个式子。
             的确不用判,因为上式 和 A(小) - D(大) > C(大) - B(小) [p]这个式子的信息是等价的。
             什么意思呢,B(小) - C(大) > D(大) - A(小)可以化为 dmin[B][C] - dmax[D][A],
             即我们判断的任然是A与D之间的关系和 B与C之间的关系,和那个[p]式子判断的东西相同。
               
         之前说的“约束信息不一定完整”,就是因为我们可能知道
         AC、AD、BC、BD 这四组关系中的某两组关系,但不一定不知道另外两组的关系,
         所以要判断两个不等式,同时也只需要两个 “判断的信息不同的 ”不等式就好了。
            ______________________________________________________________________
    剩下的就差不多了,自己化一化吧。
    2).A + B = C + D
       if((dmin[A][C]==dmax[A][C]&&dmin[B][D]==dmax[B][D]&&dmin[A][C]+dmin[B][D]==0)||dmin[A][D]==dmax[A][D]&&dmin[B][C]==dmax[B][C]&&dmin[A][D]+dmin[B][C]==0)) ans2++;
    3).C + D > A + B
       if(dmin[C][A]>dmax[B][D]||dmin[C][B]>dmax[A][D]) ans3++;

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    int dmax[55][55],dmin[55][55]; 
    int n,A,B,ans1,ans2,ans3;
    int main(){
    	char ch;
    	scanf("%d%d%d",&n,&A,&B);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++){
    			scanf(" %c",&ch);
    			if(i==j||ch=='=') dmax[i][j]=dmin[i][j]=0;
    			else if(ch=='+') dmax[i][j]=2,dmin[i][j]=1;
    			else if(ch=='-') dmax[i][j]=-1,dmin[i][j]=-2;
    			else dmax[i][j]=2,dmin[i][j]=-2;
    		}
    	for(int k=1;k<=n;k++)
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    				dmax[i][j]=min(dmax[i][j],dmax[i][k]+dmax[k][j]);
    	for(int k=1;k<=n;k++)
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    				dmin[i][j]=max(dmin[i][j],dmin[i][k]+dmin[k][j]);
    	for(int C=1;C<=n;C++)
    		for(int D=1;D<C;D++){
    			if(C==A||C==B||D==A||D==B) continue;
    			if(dmin[A][C]>dmax[D][B]||dmin[A][D]>dmax[C][B]) ans1++;
    			
    			if((dmin[A][C]==dmax[A][C]&&dmin[B][D]==dmax[B][D]&&dmin[A][C]+dmin[B][D]==0)||
    			(dmin[A][D]==dmax[A][D]&&dmin[B][C]==dmax[B][C]&&dmin[A][D]+dmin[B][C]==0)) ans2++;
    			
    			if(dmin[C][A]>dmax[B][D]||dmin[C][B]>dmax[A][D]) ans3++;
    		}
    	printf("%d %d %d",ans1,ans2,ans3);
    	return 0;
    }
    
          • 晚上
            • BOZJ 1078 [SCOI2008]斜堆

    考虑反着来依次撤掉最后一个。
    看看最后一个插入的点满足什么性质:
       它是一直向左边插入的,且它没有右子树。[p]
    但这种点不止一个。
    我们考虑,对于一个满足该性质的点x,如果它的左子树(不是叶子)中还有一个点y也满足该性质,
    那x和y到底哪个是最后一个插入的呢。答案是x。
    如果是y的话,那按照斜堆的插入方法,y点经过x点时,会swap点x的左右子树,
    即表明x在y插入之前,只有右儿子,没有左儿子(因为插入y后x只有左儿子,没有右儿子),
    不符合斜堆的性质:任何非叶子节点都不可能单独存在右儿子。
       
    所以对于那么多满足[p]的点,深度最小的点才是最后插入的。
       
    另外如果y是x的左儿子,且y是叶子节点,x和y都可以作为最后插入的点。
    为了让字典序最小(小顶堆),所以就让y是最后插入的。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #define ls lson[u]
    #define rs rson[u]
    using namespace std;
    int lson[105],rson[105],ans[105];
    int n,rt;
    void dfs(int u,int fa,int p){
    	if((!ls&&!rs)||(!rs&&ls&&lson[ls])){
    		lson[fa]=ls;
    		ans[p]=u;
    		return ;
    	}
    	dfs(ls,u,p);
    	swap(ls,rs);
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=2,x;i<=n+1;i++){
    		scanf("%d",&x);
    		if(x<100) lson[x+1]=i;
    		else rson[x-100+1]=i;
    	}
    	lson[0]=1;
    	for(int i=n+1;i>=1;i--) dfs(lson[0],0,i);
    	for(int i=1;i<=n+1;i++) printf("%d ",ans[i]-1);
    	return 0;
    }  
            • BOZJ 1079 [SCOI2008]着色方案

    神dp,这个状态定义太强了。
    因为每种颜料涂的次数不超过5次,就把这个写入状态,%%%
    f[a][b][c][d][e][l]:
        还可以涂1次的有 a 个
        还可以涂2次的有 b 个
        、、、、、、、、、、
        还可以涂5次的有 e 个——的方案数。

    (难在状态定义上,转移很简单)
    (注意:要及时加 1ll*啊!!!!!int会乘爆的)

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int mod=1000000007;
    bool vis[16][16][16][16][16][6];
    int f[16][16][16][16][16][6],t[6];
    int n;
    int dp(int a,int b,int c,int d,int e,int l){
    	long long res=1ll*f[a][b][c][d][e][l];
    	if(a+b+c+d+e==0) return 1;
    	if(vis[a][b][c][d][e][l]) return res%mod;
    	vis[a][b][c][d][e][l]=1;
    	if(a) res+=1ll*(a-(l==2))*dp(a-1,b,c,d,e,1);
    	if(b) res+=1ll*(b-(l==3))*dp(a+1,b-1,c,d,e,2);
    	if(c) res+=1ll*(c-(l==4))*dp(a,b+1,c-1,d,e,3);
    	if(d) res+=1ll*(d-(l==5))*dp(a,b,c+1,d-1,e,4);
    	if(e) res+=1ll*(    e   )*dp(a,b,c,d+1,e-1,5);
    	return f[a][b][c][d][e][l]=res%mod;
    } 
    int main(){
    	scanf("%d",&n);
    	for(int i=1,x;i<=n;i++)
    		scanf("%d",&x),t[x]++;
    	printf("%d",dp(t[1],t[2],t[3],t[4],t[5],0));
    	return 0;
    }
    
  • 相关阅读:
    Dev 之 GridControl 列表 显示底部(包括底部统计)
    DEV 之 有些控件不允许拖动。
    Split 之特殊用法
    WebSerivce与WebAPI的区别
    DevExpress的DateEdit设置显示日期和时间
    indexOf 和 lastIndexOf的区别
    DevExpress GridControl使用教程:之 添加 checkbox 复选框
    APP通用测试用例大全
    Windows下搭建easyMock
    Centos8搭建Easy-Mock详细步骤
  • 原文地址:https://www.cnblogs.com/zj75211/p/7745396.html
Copyright © 2020-2023  润新知