zoukankan      html  css  js  c++  java
  • Codeforces Round #553 div.2

    题目链接:戳我

    好久没有写CF了(实际上好久没有动脑子了),实在是惨淡至极。这几天打算每天都开virtual contest qwq......

    A

    注意情况的分类讨论qwq

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 100
    using namespace std;
    int n,ans=0x3f3f3f3f;
    char s[MAXN];
    inline int dis(char from,char to)
    {
        int cur_ans=0x3f3f3f3f;
        if(to>from) 
        {
            cur_ans=min(cur_ans,to-from);
            cur_ans=min(cur_ans,from-'A'+'Z'-to+1);
        }
        else 
        {
            cur_ans=min(cur_ans,from-to);
            cur_ans=min(cur_ans,'Z'-from+to-'A'+1);
        }
        return cur_ans;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&n);
        for(int i=1;i<=n;i++) cin>>s[i];
        for(int i=1;i+3<=n;i++) 
        {
            int cur_ans=0;
            cur_ans+=dis(s[i],'A');
            cur_ans+=dis(s[i+1],'C');
            cur_ans+=dis(s[i+2],'T');
            cur_ans+=dis(s[i+3],'G');
            ans=min(ans,cur_ans);
        }
        printf("%d
    ",ans);
        return 0;
    }
    

    B

    正解好像是DP......但是异或等于0的概率其实很小,而且还有special judge QAQ完全可以用随机化算法对吧!

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<set>
    #include<ctime>
    #define MAXN 2048
    using namespace std;
    int n,m,cnt;
    int a[MAXN][MAXN];
    struct Node{int x,y;};
    vector<Node>vec;
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        srand(time(0));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                scanf("%d",&a[i][j]);
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            int cur=rand()%m+1;
            vec.push_back((Node){i,cur});
            ans^=a[i][cur];
        }
        while(ans==0&&cnt<=10000000)
        {
            int cur=rand()%vec.size();
            ans^=a[vec[cur].x][vec[cur].y];
            vec[cur].y=rand()%m+1;
            ans^=a[vec[cur].x][vec[cur].y];
            cnt++;
        }
        if(ans==0) printf("NIE
    ");
        else 
        {
            printf("TAK
    ");
            for(int i=0;i<vec.size();i++)
                printf("%d ",vec[i].y);
        }
        // cout<<(double)clock()/CLOCKS_PER_SEC<<endl;
        return 0;
    }
    

    C

    两个long long相乘之前一定要记得取模
    区间问题不好处理,但是从1开始就比较容易的问题可以用差分解决
    1,3,5,7这种奇数序列的前缀和为(i^2),2,4,6,8这种偶数序列的前缀和为(i^2+i)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define ll long long
    #define mod 1000000007
    using namespace std;
    ll l,r;
    inline ll sum(ll x)
    {
        ll last=0,cnt1=0,cnt2=0,ans=0;
        for(ll i=1,j=1;last<x;i<<=1,j++)
        {
            // printf("i=%lld last=%lld
    ",i,last);
            if(j&1)
            {
                if(last+i<=x) cnt1+=i,last+=i;
                else cnt1+=(x-last),last=x;
            }
            else
            {
                if(last+i<=x) cnt2+=i,last+=i;
                else cnt2+=(x-last),last=x;
            }
            // printf("cnt1=%lld cnt2=%lld
    ",cnt1,cnt2);
        }
        // cout<<cnt1<<" "<<cnt2<<endl;
        cnt1%=mod,cnt2%=mod;
        ans=(ans+cnt1*cnt1%mod)%mod;
        ans=(ans+cnt2*cnt2%mod)%mod;
        ans=(ans+cnt2%mod)%mod;
        return ans;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        cin>>l>>r;
        cout<<((sum(r)-sum(l-1))%mod+mod)%mod<<endl;
        return 0;
    }
    

    D

    把式子展开一下就行了,是一个定值+(sum a[i]-b[i])
    然后贪心一下就行了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #define MAXN 100010
    using namespace std;
    int n;
    struct Node{int a,b,sum,id;}node[MAXN];
    inline bool cmp(struct Node x,struct Node y)
    {
        return x.sum>y.sum;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&node[i].a,&node[i].b);
            node[i].sum=node[i].a-node[i].b;
            node[i].id=i;
        }
        sort(&node[1],&node[n+1],cmp);
        long long ans=0;
        for(int i=1;i<=n;i++)
        {
            ans+=1ll*node[i].b*n-node[i].a;
            ans+=1ll*i*node[i].sum;
        }
        cout<<ans<<endl;
        return 0;
    } 
    

    E

    这个题都说简单可是我还是没有做出来。。。。
    题意:每次保留值为[l,r]区间的点,问(sum_{l=1}sum_{r=l+1})的联通块的个数。
    因为是一条链,所以我们可以考虑每个点的贡献。
    对于每个点,假设它是连通块里面编号最大的QAQ,那么就一定有编号i+1不在该联通块里。
    如果a[i]>a[i+1],贡献为(a[i]-a[i+1]*(n-a[i]+1))
    如果a[i]<=a[i+1],贡献为((a[i+1]-a[i])*a[i])

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define MAXN 100010
    using namespace std;
    int n;
    long long ans;
    long long a[MAXN];
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) cin>>a[i];
    	for(int i=1;i<n;i++)
    	{
    		if(a[i]<=a[i+1]) ans+=1ll*(a[i+1]-a[i])*a[i];
    		else ans+=1ll*(a[i]-a[i+1])*(n-a[i]+1);
    	}
    	cout<<ans+1ll*(n-a[n]+1)*a[n]<<endl;
    	return 0;
    }
    
    

    F

    题目大意:给你一个长度为N的数列,里面只有0或者1。可以操作K次,每次交换两个数。询问K次之后的数列中,为不下降序列的概率为多少?
    对1e9+7取模。
    不下降序列只有一种,就是前(0的个数,这里设为m)位置为0,后面的为1。
    一个神奇的DP(好吧也不神奇),就是设(dp[i][j])表示第i次操作后,前m个位置中有j个1的方案数。

    这样子我们就可以递推了。
    前m个位置中有m-j个0,j个1;后面有j个0,n-m-j个1.
    递推这个样子写:

    for(int i=1;i<=k;i++)
    	{
    		for(int j=0;j<=min(m,n-m);j++)
    		{
    			if(j+1<=min(m,n-m)) 
    				dp[i][j+1]=(dp[i][j+1]+1ll*dp[i-1][j]*(m-j)%mod*(n-m-j)%mod)%mod;
    			//0<-->1
    			dp[i][j]=(dp[i][j]+1ll*dp[i-1][j]*(m-j)%mod*j%mod)%mod;
    			//0<-->0
    			dp[i][j]=(dp[i][j]+1ll*dp[i-1][j]*j%mod*(n-m-j)%mod)%mod;
    			//1<-->1
    			dp[i][j]=(dp[i][j]+(1ll*dp[i-1][j]*(m-1)*m/2)%mod)%mod;
    			//前m中交换
    			dp[i][j]=(dp[i][j]+(1ll*dp[i-1][j]*(n-m-1)*(n-m)/2)%mod)%mod;
    			//后n-m个中交换
    			if(j-1>=0) 
    				dp[i][j-1]=(dp[i][j-1]+1ll*dp[i-1][j]*j%mod*j%mod)%mod;
    			//1<-->0
    		}
    	}
    

    但是这个样子会T......
    所以要加一个矩阵快速幂QAQ(注意计算后一定要返回值啊QAQ)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define MAXN 110
    #define mod 1000000007
    using namespace std;
    int n,k,m,nn;
    int a[MAXN],dp[MAXN][MAXN];
    struct Node{int t[MAXN][MAXN];}init,ans;
    inline int fpow(int x,int y)
    {
    	int cur_ans=1;
    	while(y)
    	{
    		if(y&1) cur_ans=1ll*cur_ans*x%mod;
    		x=1ll*x*x%mod;
    		y>>=1;
    	}
    	return cur_ans;
    }
    inline Node calc(Node x,Node y)
    {
    	Node cur_ans;
    	for(int i=0;i<=nn;i++)
    		for(int j=0;j<=nn;j++)
    			cur_ans.t[i][j]=0;
    	for(int i=0;i<=nn;i++)
    		for(int j=0;j<=nn;j++)
    			for(int p=0;p<=nn;p++)
    			{
    				cur_ans.t[i][j]=(cur_ans.t[i][j]+1ll*x.t[i][p]*y.t[p][j]%mod)%mod;
    				// printf("cur[%d][%d]=%d
    ",i,j,cur_ans.t[i][j]);
    			}
    	return cur_ans;
    }
    inline Node solve(Node x,int y)
    {
    	Node cur_ans;
    	for(int i=0;i<=nn;i++)
    		for(int j=0;j<=nn;j++)
    			cur_ans.t[i][j]=0;
    	for(int i=0;i<=nn;i++) cur_ans.t[i][i]=1;
    	while(y)
    	{
    		if(y&1) cur_ans=calc(cur_ans,x);
    		x=calc(x,x);
    		y>>=1;
    	}
    	return cur_ans;
    }
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	cin>>n>>k;
    	for(int i=1;i<=n;i++) 
    	{
    		scanf("%d",&a[i]);
    		if(a[i]==0) m++; 
    	}
    	int cur=0;
    	for(int i=1;i<=m;i++) if(a[i]==1) cur++;
    	int c1=(1ll*(m-1)*m/2)%mod;
    	int c2=(1ll*(n-m-1)*(n-m)/2)%mod;
    	nn=min(n-m,m);
    	for(int i=0;i<=nn;i++)
    	{
    		init.t[i][i]=(init.t[i][i]+(c1+c2)%mod)%mod;
    		init.t[i][i]=(init.t[i][i]+(1ll*(m-i)*i)%mod)%mod;
    		init.t[i][i]=(init.t[i][i]+(1ll*(n-m-i)*i%mod))%mod;
    		if(i+1<=nn) 
    			init.t[i][i+1]=(init.t[i][i+1]+1ll*(m-i)*(n-m-i)%mod)%mod;
    		if(i-1>=0)
    			init.t[i][i-1]=(init.t[i][i-1]+1ll*i*i%mod)%mod;
    	}
    	// for(int i=0;i<=nn;i++)
    	// {
    	// 	for(int j=0;j<=nn;j++)
    	// 		cout<<init.t[i][j]<<" ";
    	// 	cout<<endl;
    	// }
    	init=solve(init,k);
    	ans.t[0][cur]=1;
    	ans=calc(ans,init);
    	int fn=1ll*fpow(fpow(n*(n-1)/2,k),mod-2)%mod;
    	cout<<1ll*ans.t[0][0]*fn%mod<<endl;
    	return 0;
    }
    
  • 相关阅读:
    sql中保留2位小数
    C# 操作字符串,在某些特定的字符后面或前面添加其它字符
    Windows Server 2008 R2中上传和下载文件
    winform中显示标题,点击打开链接
    正则表达式
    winform重绘
    js获取元素的页面坐标
    剑指offer-从上往下打印二叉树
    剑指offer-栈的压入、弹出序列
    剑指offer-包含min函数的栈
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10764719.html
Copyright © 2011-2022 走看看