Croc Champ 2013 - Round 2 (Div. 2 Edition) 贪心+ 搜索+剪枝 + 数学

A:

直接找出最小值,看是否能被所有数整除即可

B:

判断是否出现连续的“#”>=m若果存在肯定不能调。

C:

题意:

两个人玩游戏(A,B),每个人分配一个字符串长度为2*n的字符串s1,s2,然后A先从[1~2*n]选一个数i,然后他就从s1中取走s1[i],然后是B从[1~2*n]中选一个还未曾被选过的数然j后取走s2[j]最后他们分别否会获得n个“0”,“1”他们可以任意组合这些0,1最后谁组合出来的数最大谁赢,若想等则平局。

思路:

首先分析如果出现s1[i] = s2[i] = 1的话,他们肯定会去这个“1”因为这样既保证自己得到一个1,另一方失去一个1,如果存在计数个那么最后A肯定比B多1,如果是偶数个,那么两人得到的1的个数相同,然后就看剩下的怎么取了,如果剩下的为偶数个那么第一个取的是A,首先我会把所有能够取到的1取得,然后将对方能够消除的1消除,奇数时B先取同上。然后我们判断只要先取的一方把能取的都取完了,然后对方只能获得剩下他能取的一半了。

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define ll __int64
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);


#define M 137
#define N 2000017

using namespace std;

const int inf = 100000007;
const int mod = 1000000007;

char s1[N],s2[N];

int main()
{
//    Read();
    int i;
    int n;
    scanf("%d",&n);
    scanf("%s%s",s1,s2);
    int n1 = 0;
    int n2 = 0;
    int ct = 0;
    for (i = 0; i < 2*n; ++i)
    {
        if (s1[i] == '1' && s2[i] == '1')
        {
            s1[i] = '0';
            s2[i] = '0';
            ct++;
        }
    }
    int tmp = 0;
    if (ct%2 == 1)  tmp = 1;

    for (i = 0; i < 2*n; ++i)
    {
        if (s1[i] == '1') n1++;
        if (s2[i] == '1') n2++;
    }
    int mk = (2*n - ct)/2;
    if ((2*n - ct)%2 == 1)
    {
       if (n1 > n2)
       {
           n1 = n2 + (n1 - n2)/2;
       }
       else
       {
           n2 = n1 + (n2 - n1 + 1)/2;
       }
//       printf("%d %d\n",n1,n2);
    }
    else
    {
        if (n1 > n2)
        {
            n1 = n2 + (n1 - n2 + 1)/2;
        }
        else
        {
            n2 = n1 + (n2 - n1)/2;
        }
    }

    n1 += tmp;
//    printf("%d %d\n",n1,n2);
    if (n1 > n2) printf("First\n");
    else if (n1 == n2) printf("Draw\n");
    else printf("Second\n");
    return 0;
}

 

D:

题意:
给你一个n*m的矩阵,里面的有些方格被染色了,有些没有,让我们用小于k的的颜色,将该矩形染满颜色,要求从左上角到右下角的路径中不存在两个颜色相同的。问一共有多少中可能。

思路:

暴力搜索+强剪纸

用u[i]记录每一中颜色的在已经走过的矩阵中使用的次数,如果x,y在这之前还没出现过,那么当前小方格内取x或者y所形成的方法数目是相同的利用这个剪纸可以减少很多搜索,还可以利用类似A*的,当前路径已经用了多少颜色,后边每一步还需要多少颜色,如果总和超过k就是不合法的路径。

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))

#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define ll __int64
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);


#define M 137
#define N 1025

using namespace std;


const int inf = 0x7f7f7f7f;
const int mod = 1000000007;

int state[N];
int a[1007][1007];
int s[1007][1007];
int u[11];
int n,m,k;

ll dfs(int x,int y)
{
    if (y > m) return dfs(x + 1,1);
    if (x > n) return 1;

    ll ans = 0;
    int cur = s[x - 1][y]|s[x][y - 1];

    if (n + m - x - y + __builtin_popcount(cur) >= k) return 0;//剪枝2

    ll w = -1;
    for (int v = (~cur)&((1<<k) - 1); v; v -= v&-v)
    {
        int i = state[v&-v] + 1;

        if (!(cur&(1<<(i - 1))) && (a[x][y] == i || !a[x][y]))
        {
            s[x][y] = cur|(1<<(i - 1));
            if (!u[i]++)
            {
                if (w == -1) w = dfs(x,y + 1);//剪枝1
                ans += w;
            }
            else ans += dfs(x,y + 1);
            u[i]--;
            ans %= mod;
        }
    }
    return ans;
}
int main()
{
    int i,j;
    scanf("%d%d%d",&n,&m,&k);

    for (i = 0; i < k; ++i) state[1<<i] = i;
    CL(u,0);
    for (i = 1; i <= n; ++i)
    {
        for (j = 1; j <= m; ++j)
        {
            scanf("%d",&a[i][j]);
            u[a[i][j]]++;
        }
    }

    ll ans = dfs(1,1);
    cout<<ans<<endl;
    return 0;
}

 

E:

题意:

给出n(n<= 10^14)求满足 a^3 + b^3 + c^3 + n = (a + b + c)^3 的a,b,c的个数。

思路:

首先我们能够推出公式(a + b)*(a + c) *(b + c) = n;

然后我们就可以枚举

(a + b) = i;  (a + c) = j;  (b + c) = k;    

a >= 1; b >= 1; c >= 1; === > i + j - k >= 1 ......

a <= b <= c  ;

然后求解即可。

这里好像根据线性代数对着三个方程证明一定存在可行解。

View Code
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>

#define CL(arr, val)    memset(arr, val, sizeof(arr))
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define ll __int64
#define L(x)    (x) << 1
#define R(x)    (x) << 1 | 1
#define MID(l, r)   (l + r) >> 1
#define Min(x, y)   (x) < (y) ? (x) : (y)
#define Max(x, y)   (x) < (y) ? (y) : (x)
#define E(x)        (1 << (x))
#define iabs(x)     (x) < 0 ? -(x) : (x)
#define OUT(x)  printf("%I64d\n", x)
#define lowbit(x)   (x)&(-x)
#define Read()  freopen("din.txt", "r", stdin)
#define Write() freopen("dout.txt", "w", stdout);

#define M 137
#define N 100007

using namespace std;

const int inf = 100000007;
const int mod = 1000000007;

ll fact[N];
int len;

int main()
{
//    Read();
    int i,j;
    ll n;
    while (~scanf("%I64d",&n))
    {
        if (n%3 == 1)
        {
            printf("0\n");
            continue;
        }
        n /= 3;
        len = 0;
        for (ll p = 1; p*p <= n; ++p)
        {
            if (n%p == 0)
            {
                fact[len++] = p;
            }
        }
        ll ans = 0;
        for (i = 0; i < len; ++i)
        {
            for (j = i; j < len; ++j)
            {
                ll ti = fact[i];
                ll tj = fact[j];
                ll tk = n/(fact[i]*fact[j]);

                if (tk < ti || tk < tj) break;
                if (n%(fact[i]*fact[j]) != 0) continue;
                if ((ti + tk + tj)%2 != 0) continue;

                if (ti + tk - tj >= 2 && tj + tk - ti >= 2 && ti + tj - tk >= 2)
                {
                     if (ti == tj && tj == tk) ans++;
                     else if (ti == tj || tj == tk || tk == ti) ans += 3;
                     else ans += 6;
                }

            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

 

转载于:https://www.cnblogs.com/E-star/archive/2013/04/25/3043468.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值