现在的位置: 首页 > 综合 > 正文

Codeforces Round #277(Div. 2)

2017年12月16日 ⁄ 综合 ⁄ 共 4407字 ⁄ 字号 评论关闭

A题:http://codeforces.com/contest/486/problem/A

分析:分析下奇偶就出来结果了

代码:

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <string.h>
using namespace std;
typedef long long ll;
const int N=100010;
ll arr[N];
ll dp[110][2];
ll n,m;
int main()
{
        while(cin>>n)
        {
            if(n&1)
            {
                cout<<n*-1+n/2<<endl;
            }
            else
            {
                cout<<n/2<<endl;
            }
        }
}

B题:http://codeforces.com/contest/486/problem/B

分析:题目是说有一个01矩阵A,然后根据A可以得到矩阵B,规则是Bij=1如果i行或者j列至少有一个1,否则Bij为0. 现在已知B矩阵,求问能否找到一个合适的A矩阵。

可以看出,如果B矩阵元素是0,那么A矩阵中该元素所在的行和列肯定也要全为0,故此可以在最开始把A全部设置成1,再把B中为0的对应的行和列在A中设为0,最后再通过得到的A来求B,看是否一致,不一致的话,则返回NO

代码:

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <string.h>
using namespace std;
typedef long long ll;
const int N=100010;
int a[110][110];
int b[110][110];
int c[110][110];
ll n,m;
int main()
{
        while(cin>>n>>m)
        {
            for(int i=0;i<n;i++)
                for(int j=0;j<m;j++)
                {
                    cin>>a[i][j];
                    b[i][j]=1;
                }
            for(int i=0;i<n;i++)
                for(int j=0;j<m;j++)
                {
                    if(a[i][j]==0)
                    {
                        for(int k=0;k<n;k++)
                            b[k][j]=0;
                        for(int k=0;k<m;k++)
                            b[i][k]=0;
                    }
                }
                memset(c,0,sizeof(c));
                for(int i=0;i<n;i++)
                    for(int j=0;j<m;j++)
                    {
                        for(int k=0;k<n;k++)
                            c[i][j]|=b[k][j];
                        for(int k=0;k<m;k++)
                            c[i][j]|=b[i][k];
                    }
                    bool flag = true;
                    for(int i=0;i<n;i++)
                        for(int j=0;j<m;j++)
                        {
                            if(a[i][j]!=c[i][j])
                                flag = false;
                        }
                    if(flag)
                    {
                        cout<<"YES"<<endl;
                        for(int i=0;i<n;i++)
                        {
                            for(int j=0;j<m;j++)
                                cout<<b[i][j]<<" ";
                            cout<<endl;
                        }
                    }
                    else
                    {
                        cout<<"NO"<<endl;
                    }
        }
}

c题:http://codeforces.com/contest/486/problem/C

分析:题意是问要经过多少步使得给定字符串编程回文字符串,首先可以肯定得是,指针只需要在字符串的一半部分移动就行了,比如长度为8的字符串,当前位置为3,那么字符串最多也只要在位置为1234的地方进行改变就行了,因为该左边部分和改右边部分是等价的,但是去过指针在左边但是去改右边移动的步数会比较多,其次,如果都转换到当前指针在左边之后,还要判断指针是先左后右还是先右后左,两种不同的结果,同时要注意最左和最右需要走到那边,比如第1个位置和第8个位置是一样的,那么最左只需要走到第二个位置就行了。。。比赛时代码写的比较乱。。。

代码:

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <string.h>
using namespace std;
typedef long long ll;
const int N=100010;
int a[110][110];
int b[110][110];
int c[110][110];
int n,m;
int main()
{
        while(cin>>n>>m)
        {
            string s;
            cin>>s;
            m = min(m,n+1-m);
            m--;
            int ret = 0;
            int start = 0;
            while(start<n-1-start&&s[start]==s[n-1-start])
                start++;
            if(start>=n-1-start)
            {
                cout<<0<<endl;
                continue;
            }
            ret+=abs(m-start);
            int last = start;
            while(start<n-1-start)
            {
                int t1 = s[start]-'a';
                int t2 = s[n-1-start]-'a';
                int diff = max(t1,t2)-min(t1,t2);
                int t = min(diff,26-diff);
                if(t!=0)
                {
                    ret+=t;
                    ret+=abs(start-last);
                    last = start;
                }
                start++;
            }
            int ret1 = 0;
            int start1 = n%2==0?n/2-1:n/2;
            while(start1>=0&&s[start1]==s[n-1-start1])
                start1--;
            if(start1<0)
            {
                cout<<0<<endl;
                continue;
            }
            ret1+=abs(m-start1);
            int last1 = start1;
            while(start1>=0)
            {
                int t1 = s[start1]-'a';
                int t2 = s[n-1-start1]-'a';
                int diff = max(t1,t2)-min(t1,t2);
                int t = min(diff,26-diff);
                if(t!=0)
                {
                    ret1+=t;
                    ret1+=abs(start1-last1);
                    last1 = start1;
                }
                start1--;
            }
            ret = min(ret,ret1);
            cout<<ret<<endl;
        }
        return 0;
}

D题:http://codeforces.com/contest/486/problem/D

比赛时没做。。。因为太晚了舍友要睡觉= =今天看了下题目,可以肯定得是树形DP,一般树形DP都是用dp[i]来表示以i为root节点得到的什么什么数。。。

参考了下别人的代码,这里用dfs(i)返回以i为节点,且i节点的权重最大的情况下,有多少个符合条件的子树,这样的话,只需要遍历每个节点,然后把每个节点当成root顶点,计算有多少符合条件的子树即可,要注意的是,这里可能会产生重复的字符,故需要用visited[i]来判断以i为root且最大为weight[i]的子树是否已经处理过

代码:

#include <iostream>
#include <algorithm>
#include <string>
#include <map>
#include <vector>
#include <cstring>
#include <string.h>
#include <cstdio>
#include <stack>
#include <iomanip>
#include <math.h>
using namespace std;
typedef long long ll;

const int mod = 1e9+7;
const int N=3010;
ll x,y,m,n,k;
pair<ll,ll>  arr[N];
bool deleted[N];
string s;
int a,b,c,d;
vector<int> v[N];
bool visited[N];
int weight[N];
ll dfs(int cur,int par,int up,int down)
{
    if(weight[cur]<down||weight[cur]>up)
        return 0;
    if(weight[cur]==up&&!visited[cur])
        return 0;
    ll ans = 1;
    for(int i=0;i<v[cur].size();i++)
    {
        int next = v[cur][i];
        if(next==par)continue;
        ans = (ans*(dfs(next,cur,up,down)+1))%mod;
    }
    return ans;
}
int main()
{
    while(cin>>d>>n)
    {
        
        for(int i=1;i<=n;i++)
        {
            cin>>weight[i];
            v[i].clear();
            visited[i]=true;
        }
        for(int i=0;i<n-1;i++)
        {
            int a,b;
            cin>>a>>b;
            v[a].push_back(b);
            v[b].push_back(a);
        }
        ll ans = 0;
        for(int i=1;i<=n;i++)
        {
            ans = (ans+dfs(i,-1,weight[i],weight[i]-d))%mod;
            visited[i]=false;
        }
        cout<<ans<<endl;
    }


    return 0;
}

抱歉!评论已关闭.