Codeforces Round#267 B、C 、D

B. Fedor and New Game
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

After you had helped George and Alex to move in the dorm, they went to help their friend Fedor play a new computer game «Call of Soldiers 3».

The game has (m + 1) players and n types of soldiers in total. Players «Call of Soldiers 3» are numbered form 1 to (m + 1). Types of soldiers are numbered from 0 to n - 1. Each player has an army. Army of the i-th player can be described by non-negative integer xi. Consider binary representation of xi: if the j-th bit of number xi equal to one, then the army of the i-th player has soldiers of the j-th type.

Fedor is the (m + 1)-th player of the game. He assume that two players can become friends if their armies differ in at most k types of soldiers (in other words, binary representations of the corresponding numbers differ in at most k bits). Help Fedor and count how many players can become his friends.

Input

The first line contains three integers nmk (1 ≤ k ≤ n ≤ 20; 1 ≤ m ≤ 1000).

The i-th of the next (m + 1) lines contains a single integer xi (1 ≤ xi ≤ 2n - 1), that describes the i-th player's army. We remind you that Fedor is the (m + 1)-th player.

Output

Print a single integer — the number of Fedor's potential friends.

Sample test(s)
input
7 3 1
8
5
111
17
output
0
input
3 3 3
1
2
3
4
output
3

水题,看前m个数有多少个和第m+1个数二进制不相同位数小于k。

代码:

/**
 * @author neko01
 */
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
#define INF 0x3f3f3f3f
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
#define pb push_back
#define mp(a,b) make_pair(a,b)
#define clr(a) memset(a,0,sizeof a)
#define clr1(a) memset(a,-1,sizeof a)
#define dbg(a) printf("%d\n",a)
typedef pair<int,int> pp;
const double eps=1e-8;
const double pi=acos(-1.0);
int a[1111];
int main()
{
    int n,m,k,x;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=0;i<m;i++)
        scanf("%d",&a[i]);
    scanf("%d",&x);
    int ans=0;
    for(int i=0;i<m;i++)
    {
        int sum=0;
        for(int j=0;j<n;j++)
            if(((1<<j)&a[i])!=((1<<j)&x)) sum++;
        if(sum<=k) ans++;
    }
    printf("%d\n",ans);
    return 0;
}

C. George and Job
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

The new ITone 6 has been released recently and George got really keen to buy it. Unfortunately, he didn't have enough money, so George was going to work as a programmer. Now he faced the following problem at the work.

Given a sequence of n integers p1, p2, ..., pn. You are to choose k pairs of integers:

[l1, r1], [l2, r2], ..., [lk, rk] (1 ≤ l1 ≤ r1 < l2 ≤ r2 < ... < lk ≤ rk ≤ nri - li + 1 = m), 

in such a way that the value of sum  is maximal possible. Help George to cope with the task.

Input

The first line contains three integers nm and k (1 ≤ (m × k) ≤ n ≤ 5000). The second line contains n integers p1, p2, ..., pn (0 ≤ pi ≤ 109).

Output

Print an integer in a single line — the maximum possible value of sum.

Sample test(s)
input
5 2 1
1 2 3 4 5
output
9
input
7 1 3
2 10 7 18 5 33 0
output
61

水dp,dp[i][j]表示到第i个数有j段的最大值,dp[i][j]=max(dp[i-1][j],dp[i-m][j-1]+sum(i-m,i))

代码:

/**
 * @author neko01
 */
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
#define pb push_back
#define mp(a,b) make_pair(a,b)
#define clr(a) memset(a,0,sizeof a)
#define clr1(a) memset(a,-1,sizeof a)
#define dbg(a) printf("%d\n",a)
typedef pair<int,int> pp;
const double eps=1e-9;
const double pi=acos(-1.0);
const int N=5005;
LL dp[N][N];
LL sum[N];
int a[N];
int main()
{
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=k;j++)
        {
            if(i>=m)
                dp[i][j]=max(dp[i-1][j],dp[i-m][j-1]+(sum[i]-sum[i-m]));
            else
                dp[i][j]=dp[i-1][j];
        }
    }
    printf("%I64d\n",dp[n][k]);
    return 0;
}


D. Fedor and Essay
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

After you had helped Fedor to find friends in the «Call of Soldiers 3» game, he stopped studying completely. Today, the English teacher told him to prepare an essay. Fedor didn't want to prepare the essay, so he asked Alex for help. Alex came to help and wrote the essay for Fedor. But Fedor didn't like the essay at all. Now Fedor is going to change the essay using the synonym dictionary of the English language.

Fedor does not want to change the meaning of the essay. So the only change he would do: change a word from essay to one of its synonyms, basing on a replacement rule from the dictionary. Fedor may perform this operation any number of times.

As a result, Fedor wants to get an essay which contains as little letters «R» (the case doesn't matter) as possible. If there are multiple essays with minimum number of «R»s he wants to get the one with minimum length (length of essay is the sum of the lengths of all the words in it). Help Fedor get the required essay.

Please note that in this problem the case of letters doesn't matter. For example, if the synonym dictionary says that word cat can be replaced with word DOG, then it is allowed to replace the word Cat with the word doG.

Input

The first line contains a single integer m (1 ≤ m ≤ 105) — the number of words in the initial essay. The second line contains words of the essay. The words are separated by a single space. It is guaranteed that the total length of the words won't exceed 105 characters.

The next line contains a single integer n (0 ≤ n ≤ 105) — the number of pairs of words in synonym dictionary. The i-th of the next n lines contains two space-separated non-empty words xi and yi. They mean that word xi can be replaced with word yi (but not vise versa). It is guaranteed that the total length of all pairs of synonyms doesn't exceed 5·105 characters.

All the words at input can only consist of uppercase and lowercase letters of the English alphabet.

Output

Print two integers — the minimum number of letters «R» in an optimal essay and the minimum length of an optimal essay.

Sample test(s)
input
3
AbRb r Zz
4
xR abRb
aA xr
zz Z
xr y
output
2 6
input
2
RuruRu fedya
1
ruruRU fedor
output
1 10

题意:给m个单词,然后给n组变换,表示前一个单词可以变成后一个,求原来m个单词的一种变换使字母r数尽可能少,相同则取单词总长度最小。

容易想到map离散化后给可以转换的连边建图,这个图可能存在环,所以就tarjan缩下点,每个强连通分量取r最少的长度短的,这样就变为一个新的有向无环图,在这个图上dp,一个点u的r数量是它可以达到的点的最小的,然后就完了。注意有极端数据结果会超int

/**
 * @author neko01
 */
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
#define pb push_back
#define mp(a,b) make_pair(a,b)
#define clr(a) memset(a,0,sizeof a)
#define clr1(a) memset(a,-1,sizeof a)
#define dbg(a) printf("%d\n",a)
typedef pair<int,int> pp;
const int INF=0x3f3f3f3f;
const double eps=1e-9;
const double pi=acos(-1.0);
const int N=500005;
const int M=500005;
int head[N];
int dfn[N],low[N];
int belong[N];  //节点i属于哪个强连通分量
int num[N];   //强连通分量i的节点数
bool isstack[N];  //是否在栈中
int stack[N];
vector<int>g[N];
struct Edge{
    int to,next;
}edge[M];
int scc,top,cnt,tol;  //强连通分量个数,栈顶,时间戳
pp f[N];   //每个单词信息
pp F[N];
int word[N];
char s[N];
bool vis[N];
int T=0;  //单词总数
map<string,int>mymap;
void init()
{
    clr1(head);
    clr(dfn);
    //clr(isstack);
    //scc=top=cnt=tol=0;
}
void add(int u,int v)
{
    edge[tol].to=v;
    edge[tol].next=head[u];
    head[u]=tol++;
}
void tarjan(int u)
{
    dfn[u]=low[u]=++cnt;
    stack[++top]=u;
    isstack[u]=1;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].to;
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(isstack[v])  //回边
        {
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(dfn[u]==low[u])
    {
        int t;
        scc++;
        F[scc]=mp(INF,INF);
        do
        {
            t=stack[top--];
            isstack[t]=0;
            belong[t]=scc;
            F[scc]=min(F[scc],f[t]);
        }while(u!=t);
    }
}
int input()
{
    scanf("%s",s);
    int num1=0,num2=strlen(s);
    for(int i=0;i<num2;i++)
    {
        s[i]=tolower(s[i]);
        num1+=s[i]=='r';
    }
    string he=s;
    if(mymap[s]!=0)
        return mymap[he];
    mymap[he]=++T;
    f[T]=mp(num1,num2);
    return T;
}
void dfs(int u)
{
    vis[u]=true;
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i];
        if(!vis[v]) dfs(v);
        F[u]=min(F[v],F[u]);
    }
}
int main()
{
    int m,n;
    scanf("%d",&m);
    for(int i=0;i<m;i++)
        word[i]=input();
    scanf("%d",&n);
    init();
    for(int i=0;i<n;i++)
    {
        int u=input();
        int v=input();
        add(u,v);
    }
    for(int i=1;i<=T;i++)
        if(!dfn[i]) tarjan(i);
    for(int i=1;i<=T;i++)
    {
        for(int j=head[i];j!=-1;j=edge[j].next)
        {
            int u=belong[i];
            int v=belong[edge[j].to];
            if(u!=v) g[u].pb(v);
        }
    }
    for(int i=1;i<=scc;i++)
        dfs(i);
    LL ans1=0,ans2=0;
    for(int i=0;i<m;i++)
    {
        int x=belong[word[i]];
        ans1+=F[x].first;
        ans2+=F[x].second;
    }
    printf("%I64d %I64d\n",ans1,ans2);
    return 0;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值