Codeforces Round #139 (Div. 2)

这次做出了三道题,三道题都过了,可惜出得太慢了(比赛二十分钟了才开始做).Rating = 1651+41 = 1692. 诶.继续Div 2吧>_<!

 

A:

就对每层的三个数top,l,r满足

(l != top && r!= top &&l!=7-top && r!=7-top && l+r!=7)条件就是合法的.

#include<iostream>
#include<cstdio>

using namespace std;

int n,top,l,r;
bool flag;

int main()
{
    cin >> n;
    cin >> top;
    flag = 1;
    for (int i = 0;i<n;++i)
    {
        cin>> l >> r;
        if (l != top && r!= top && l!=7-top && r!=7-top && l+r!=7)
        {
            top = 7-top;
        } else
        {
            flag = 0;
        }
    }
    if (flag) cout << "YES" << endl; else
    cout << "NO" << endl;
    return 0;
}



B:

  • F(k, n) = 0, for integer n, 1 ≤ n < k;
  • F(k, k) = 1;
  • F(k, n) = F(k, n - 1) + F(k, n - 2) + ... + F(k, n - k), for integer n, n > k.

按照这个规则,算出所有小于s的f(k,n).

然后从大到小贪心就可以了.正确性的保证是f(k,n)>f(k,n-1)+f(k,n-2).

#include<iostream>
#include<cstdio>

using namespace std;

int s,k;
long long f[10000];
int cnt  = 0;
int Stack[1000];
int tp;

int main()
{
    cin >> s >> k;
    f[0] = 1;
    tp = 0;
    while (f[tp]<s)
    {
        ++tp;
        f[tp] = 0;
        for (int i = 1;i<=k;++i)
        if (tp-i>=0)
        {
            f[tp] += f[tp-i];
        } else break;
    }
    if (f[tp]>s) --tp;
   // for (int i = 0;i<=tp;++i) cout << f[i] << endl;


    while (s>0 && tp >= 0)
    {
        if ( s - f[tp] >= 0)
        {
            s -= f[tp];
            Stack[cnt] = f[tp];
            ++cnt;
        }
        //cout << s << endl;
        --tp;
    }
    if (cnt == 1)
    {
        cout << "2" << endl;
        cout << "0 "<<Stack[0] << endl;
    } else{
        cout << cnt << endl;
    for (int i = cnt-1;i>0;--i) cout << Stack[i] << " ";
    cout << Stack[0] << endl;
    }
    return 0;

}


C:

用动态规划做,

F[i][0..1]分别使前i组满足题设且最后一段为黑或白的最小改变数.

l  f[i][0] = min(f[i][0],f[i-j][1]+n*j-sum[i]+sum[i-j]);

l  f[i][1] = min(f[i][1],f[i-j][0]+sum[i]-sum[i-j]);

l  sumi表示第前i列的黑格个数.

#include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>

using namespace std;

string ma[1001];
int b[1001],sum[1001];
int f[1001][2];
int n,m,x,y;

int main()
{
    cin >> n >> m >> x >> y;
    for (int i = 0;i<n;++i) cin >> ma[i];
    for (int i = 1;i<=m;++i)
    {
        b[i] = 0;
        for (int j= 0;j<n;++j)
            b[i] += (ma[j][i-1] == '#');
        sum[i] = sum[i-1]+b[i];
    }
    f[0][0] = f[0][1] = 0;
    for (int i = 1;i<=m;++i) f[i][0] = f[i][1] = 1000000000;

    for (int i = 1;i<=m;++i)
    {
        for (int j = x;j<=y;++j)
        if (i-j>=0)
        {
            f[i][0] = min(f[i][0],f[i-j][1]+n*j-sum[i]+sum[i-j]);
            f[i][1] = min(f[i][1],f[i-j][0]+sum[i]-sum[i-j]);

        }
    }
    cout << min(f[m][0],f[m][1]) << endl;

    return 0;
}



D:

仍旧是动态规划,

F[i][j][opt]表示头在(I,j)状态为opt(opt用2*(len-1)位来表示蛇的形态,用两位来表示(i-1,i)的方位,方位显然是四个,于是就两位就可以了).

空间复杂度大致是15*15*(1<<16)

转移时每次4次.四个方向.

#include<iostream>
#include<cstdio>
#include<string>
#include<queue>

using namespace std;

string ma[15];
int dp[15][15][1<<16];
int in[15][15];

int dirx[4]={0,1,0,-1};
int diry[4]={1,0,-1,0};

struct NODE
{
    int x,y,opt;
};

queue<NODE> que;
int n,m,len,opt,sx,sy,tx,ty;
int mask;
const int inf = 1000000000;

int getDir(int x,int y,int num)
{
    for (int i = 0;i<4;++i)
    if (x+dirx[i]>=0 && x+dirx[i]<n && y+diry[i]>=0 && y+diry[i]<m
        && ma[x+dirx[i]][y+diry[i]] == '0'+num)
    {
        return i^2;
    }
    return 0;
}

int main()
{
    cin >> n >> m;
    for (int i = 0;i<n;++i) cin >> ma[i];
    opt = 0;
    for (int i = 0;i<n;++i)
    {

        for (int j = 0;j<m;++j)
        {
            if (ma[i][j]>='0' && ma[i][j]<='9')
            {
                if (ma[i][j] == '1')
                {
                    sx = i;
                    sy = j;
                } else
                {
                    opt |= (getDir(i,j,ma[i][j]-'1')<<((ma[i][j]-'2')*2));
          //          cout << i << " " << j << " " << (getDir(i,j,ma[i][j]-'1')) << endl;
                }
                len = max(len,ma[i][j]-'1');
            }
            if (ma[i][j] == '@') {tx =  i; ty = j;}
        }
    }
    mask = (1<<(len*2))-1;

    que.push((NODE){sx,sy,opt});
    dp[sx][sy][opt] = 1;
    int tag;// excellent! 这让我们没必要每次清零in
    while (!que.empty())
    {
        int x = que.front().x;
        int y = que.front().y;
        int opt = que.front().opt;
        int dx = x,dy = y, dopt = opt;
        in[dx][dy] = ++tag;
        for (int i = 0;i<len-1;++i)
        {
            int dir = (dopt & 3);
            dx += dirx[dir];
            dy += diry[dir];
            dopt >>= 2;
            in[dx][dy] = tag;
        }
        que.pop();
        for (int i = 0;i<4;++i)
        {
            dx = x + dirx[i];
            dy = y + diry[i];
            dopt = ( ((opt<<2) & mask) | (i^2) );
            if (dx<0 || dx>=n || dy<0 || dy>=m
                || ma[dx][dy] == '#' || in[dx][dy] == tag
                || dp[dx][dy][dopt]>0) continue;
            dp[dx][dy][dopt] = dp[x][y][opt]+1;
            que.push((NODE){dx,dy,dopt});
        }
    }
    int ans = inf;
    for (int i = 0;i<1<<16;++i)
    if (dp[tx][ty][i]>0)
    {
        ans = min(ans,dp[tx][ty][i]);
    }
    if (ans == inf) cout << "-1" << endl; else
    cout << ans-1 << endl;

    return 0;
}



E:

果断智商捉鸡啊…围观大神们代码,发现神奇的大家都弄了个表,脑小理解不能,直到出了题解… 梅森数什么的…不和谐啊.这种东西居然大家都知道?下面是官网的题解.

Author is Ripatti .

You havez = [x / 2] + y + xy. That is equivalent to

z = [2k / 2] + y + 2ky,where x = 2k, k > 0
or
z = [(2k + 1) / 2] + y + (2k + 1)y, where x = 2k + 1, k ≥ 0.

z = k + y + 2ky, k > 0
or
z = k + y + (2k + 1)y, k ≥ 0.

Stillmore steps:

2z + 1 = 2k + 2y + 4ky + 1, k > 0
or
z + 1 = k + 2y + 2ky + 1, k ≥ 0.

2z + 1 = (2k + 1)(2y + 1), k > 0
or
z + 1 = (2y + 1)(k + 1), k ≥ 0.

From the2nd equation you can see than z should be 2t - 1 because otherwise z + 1 willhave odd divisor and we can build solution. From the 1st equation you can seethat 2t + 1 - 1 should be prime, otherwise we also can build solution. If z = 2t - 1and 2t + 1 - 1 is prime, obliviously there are no solutions.

 

#include <iostream>
#include <cstdio>

using namespace std;

const int MOD = 1000000007;

int a[40] = {2,3,5,7,13,17,19,31,61,89,107,127,521,607,1279,2203,2281,3217,4253,4423,9689,9941,11213,19937,21701,23209,44497,
             86243,110503,132049,216091,756839,859433,1257787,1398269,2976221,3021377,6972593,13466917,20996011};

int main() {
  int n;
  scanf("%d",&n);
  int x = 1;
  for (int i=1;i<a[n-1];i++) {
    x *= 2;
    if (x >= MOD) x -= MOD;
  }
  printf("%d\n",(x+MOD-1) % MOD);
  return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值