2019湖南多校第二场-20190317

(有问题欢迎提出来

A:Potato Sacks

Solved.
没看这题。

int dp[50];
int main() {
    int t;
    scanf("%d",&t);
    int pos=0;
    while(t--) {
        int mx;
        scanf("%d%d",&pos,&mx);
        memset(dp,0,sizeof(dp));
        dp[0]=1;
        for(int i=0;i<10;i++){
            int a;
            scanf("%d",&a);
            for(int i=mx-a;i>=0;i--)
            dp[i+a]=dp[i]|dp[i+a];
        }
        printf("%d ",pos);
        puts(dp[mx]?"YES":"NO");
    }
    return 0;
}

B:Moving Buildings

Unsolved.
神奇的汉诺塔。


C:Hedwig’s Ladder

Solved.
写完发现就一个样例没过,比答案多1。自己手算之后发现自由偶数才会多1,犹豫要不要交。。。经过长时间神游后。。。打表发现真的是这样的。。。就过了。

int main() {
    c[1] = 2; c[2] = 4;
    for(int i = 3; i <= 1000; ++i) {
        c[i] = (c[i-1] + c[i-2])%mod;
    }
    int t;scanf("%d",&t);
    while(t--) {
        int n, x; scanf("%d%d",&x, &n);
        LL ans = c[n];
        if(n%2==0) ans = (ans-1+mod)%mod;
        printf("%d %lld\n", x, ans);
    }
    return 0;
}

E:What time is it anyway?

Solved.

sb的bug,删掉一句话就过了。。。一摸一样的写法,只能让队友重写了一遍,然后过了。。。

const int maxn=1e6+5;
map<pii, int> mp, mp1;
pii now[maxn], cha[maxn];
char s[maxn];
int main() {
    int t;scanf("%d",&t);
    while(t--) {
        int n, x;
        mp.clear();
        scanf("%d%d",&x, &n);
        for(int i = 0; i < n; ++i) {
            scanf("%s", s);
            int a = 0, b = 0, len = strlen(s), flag = 1;
            for(int j = 0; j < len; ++j) {
                if(s[j] == ':') {
                    flag = 0;continue;
                }
                if(flag) a = a * 10 + s[j]-'0';
                else b = b * 10 + s[j]-'0';
            }
            now[i] = {a, b};
            assert(b>=0);assert(b<60);
        }
        for(int i = 0; i < n; ++i) {
            scanf("%s", s);
            int a = 0, b = 0, len = strlen(s), flag = 1, f = 1;
            if(s[0] == '+') f = 0;
            for(int j = 1; j < len; ++j) {
                if(s[j] == ':') {
                    flag = 0;
                    continue;
                }
                if(flag) a = a * 10 + s[j]-'0';
                else b = b * 10 + s[j]-'0';
            }
            a %= 12;
            if(f == 0) {
                if(b == 0) a = 12 - a;
                else {
                    a = 11 - a;b = 60 - b;
                }
            }
            a %= 12;
            cha[i] = {a, b};
            assert(b>=0);assert(b<60);
            mp[cha[i]]++;
        }
        pii aa;
        int cnt = 0;
        mp1.clear();
        for(int i = 0; i < n; ++i) {
            int a = now[0].fi + cha[i].fi, b = now[0].se + cha[i].se;
            if(b >= 60) a += b/60, b %= 60;
            a %= 12;
            pii tmp = {a, b};
            mp[cha[i]] --;
            int flag = 1;
            for(int j = 1; j < n; ++j) {
                int x = 12, y = tmp.se-now[j].se;
                if(y < 0) y += 60, x = 11;
                x += tmp.fi-now[j].fi;
                x = (x+12)%12;
                assert(y >= 0); assert(y < 60);
                if(mp[make_pair(x, y)] == 0) {
                    flag = 0;
                    break;
                }
                mp[make_pair(x, y)] --;
            }
            if(flag && mp1[tmp] == 0) {
                cnt++;
                aa = tmp;
                mp1[tmp] = 1;
            }
            mp.clear();
            for(int j = 0; j < n; ++j) mp[cha[j]]++;
        }
        printf("%d ", x);
        if(aa.fi == 0) aa.fi = 12;
        if(cnt == 0) printf("none\n");
        else if(cnt == 1) printf("%d:%02d\n", aa.fi, aa.se);
        else printf("%d\n",cnt);
    }
    return 0;
}

F:Left-Right-Win

Unsolved.


G:The Erdös-Straus Conjecture

Upsolved.
暴力枚举 a : [ n / 4 + 1 , n / 4 + 10 ] a:[n/4+1,n/4+10] a[n/4+1,n/4+10],得到分数 x y \frac xy yx,暴力枚举 b b b [ y / x + 1 , 2 ∗ y / x ] [y/x+1,2*y/x] [y/x+1,2y/x],就可以过了。

#include<bits/stdc++.h>
#define fi first
#define se second
#define eb emplace_back
using namespace std;
//typedef __int128 LL;
typedef long long LL;
typedef pair<int, int> pii;

const int MXN = 5e4 + 5;

int n;
struct lp {
    uLL a, b, c;
}cw[MXN];
LL gcd(LL a, LL b) {
    return b==0?a:gcd(b, a%b);
}
void solve(int n) {
    if(n == 2) {
        cw[n] = {1, 2, 2};return ;
    }
    LL a = n / 4 + 1, b, c, last = n / 4 + 10;
    LL x, y, x1, y1, tmp;
    int flag = 0;
    while(a <= last) {
        y = a * n;
        x = 4 * a - n;
        //printf("-%lld %lld\n", x, y);
        tmp = gcd(x, y);
        x /= tmp; y /= tmp;
        //printf("%lld %lld %lld*\n", a, x, y);
        LL tb = y / x + 1, bmax = 2*y/x;
        //printf("%lld %lld**\n", tb, bmax);
        for(; tb <= bmax; ++tb) {
            b = tb;
            y1 = tb * y;
            x1 = x * tb - y;
            if(y1 % x1 == 0) {
                c = y1/x1;
                flag = 1;
                break;
            }
        }
        if(flag) break;
        ++ a;
    }
    cw[n] = {a, b, c};
}
int main() {
    //for(int i = 4560; i <= 4660; ++i) solve(i),cout<<i<<" ";
    int tim, x; scanf("%d", &tim);
    while(tim --) {
        scanf("%d%d", &x, &n);printf("%d ", x);
        solve(n);
        printf("%lld %lld %lld\n", cw[n].a, cw[n].b, cw[n].c);
    }
    return 0;
}

H:Subprime Fibonacci Sequence

Solved.
一道sb题,我一直在想怎么快速找循环节。。。结果题目直接把方法告诉你了。。

#include<bits/stdc++.h>
using namespace std;
const int MXN = 1e6 + 4;
int noprime[MXN], pp[MXN], pcnt, minp[MXN];
int f[MXN];

void init() {
    noprime[0] = noprime[1] = 1;
    minp[1] = 1;
    for(int i = 2; i < MXN; ++i) {
        if(!noprime[i]) pp[pcnt++] = i, minp[i] = i;
        for(int j = 0; j < pcnt && pp[j]*i < MXN; ++j) {
            noprime[pp[j]*i] = 1;
            minp[i*pp[j]] = i;
            if(i % pp[j] == 0) break;
        }
    }
}
int main() {
    fin();
    init();
    int caset;
    scanf("%d", &caset);
    while(caset--) {
        int x, n, a0, a1;
        scanf("%d%d%d%d", &x, &n, &a0, &a1);
        f[0] = a0;
        f[1] = a1;
        for(int i = 2; i <= n+1; ++i) {
            f[i] = minp[f[i-1]+f[i-2]];
        }
        int k = -1, k1 = -1;
        for(int i = 0; i < n - 1; ++i) {
            if(f[i] == f[n-2] && f[i+1] == f[n-1]) {
                k = i;break;
            }
        }
        for(int i = k+1; i < n - 1 && k != -1; ++i) {
            if(f[i] == f[k] && f[i+1] == f[k+1]) {
                k1 = i;break;
            }
        }
        int lca = k1-k;
        int fir = k, tmp = n-2;
        while(fir >= 0) {
            if(f[fir] != f[tmp]) break;
            -- fir; -- tmp;
        }
        fir ++;
        if(k1 == -1) {
            printf("%d %d %d\n", x, n, 0);
            printf("%d\n", f[n]);
            continue;
        }
        printf("%d %d %d\n", x, lca + fir + 1, lca);
        assert(lca >= 1);
        int last = 0;
        for(int i = fir, j = 1; j <= lca + 2; ++i, ++j) {
            printf("%d", f[i]);
            if((j % 20 == 0)) printf("\n"), last = 1;
            else printf(" "), last = 0;
        }
        if(last == 0) printf("\n");
    }
    return 0;
}


J:Pinemi Puzzles

Upsolved.
数独: d f s dfs dfs+剪枝
c a m p camp camp d l s dls dls也出了一道这种题
剪枝1:
记录每行每列空着的格子数量和已经填的棒子的数量。搜索过程中要保证一定凑出每行每列10个棒子。
k o n g [ x ] kong[x] kong[x]表示这一行或这一列空着的格子的数量(也就是 − 1 -1 1的数量);
s u m [ x ] sum[x] sum[x]表示这一行或这一列已经填了的棒子的数量。
如果 k o n g [ x ] &gt; 10 − s u m [ x ] kong[x]\gt 10-sum[x] kong[x]>10sum[x] c o n t i n u e continue continue,因为每个格子至少放一个棒子。
如果 k o n g [ x ] ∗ 3 &lt; 10 − s u m [ x ] kong[x]*3\lt 10-sum[x] kong[x]3<10sum[x] c o n t i n u e continue continue,因为每个格子至多放三个棒子。
剪枝2:
记录每个数字周围空着的格子数量和已经填的棒子的数量。
剪枝方法同上。
这个剪枝要把每个 − 1 -1 1的格子旁边的正数的位置预处理存起来会快一点。

有了这两个剪枝基本上这题就过了。

#include<bits/stdc++.h>
#define fi first
#define se second
#define eb emplace_back
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;

const int INF = 0x3f3f3f3f;
const int MXN = 4e5 + 7;

int n, m;
int ar[11][11], ans[11][11], nd[11][11], bl[11][11];//储存周围需要的棍子数量
int dir[8][2] = {1,0,-1,0,0,1,0,-1,1,1,1,-1,-1,1,-1,-1};
std::vector<int> rm[11*11];//储存-1周围有需要的格子
std::vector<int> vs;
int kong[11+11], sum[11+11];//每行每列空着的位置和已经填的棒子数量
int flag;
bool check(int x, int y, int v) {
    int id = (x-1)*10 + y, px, py;
    if(v > 0) {
        if(kong[x] == 1 && sum[x] + v != 10) return 0;
        if(kong[10+y] == 1 && sum[10+y] + v != 10) return 0;
        if(sum[x] + v > 10) return 0;
        if(sum[10+y] + v > 10) return 0;
        if(10-sum[x]-v < kong[x]-1) return 0;
        if(10-sum[x]-v > 3*(kong[x]-1)) return 0;
        if(10-sum[10+y]-v > 3*(kong[10+y]-1)) return 0;
    }
    for(auto as: rm[id]) {
        px = (as-1)/10+1, py = as % 10;
        py = (py==0?10:py);
        if(v > nd[px][py]) return 0;
        if(bl[px][py] == 0 || nd[px][py] == 0) return 0;
        if(nd[px][py] - v < bl[px][py] - 1) return 0;
        if(nd[px][py] - v > 3*(bl[px][py] - 1)) return 0;
    }
    return 1;
}
void gao(int x, int y, int v) {
    int id = (x-1)*10 + y, px, py;
    if(v > 0) kong[x] --, kong[10+y]--,sum[x]+=v,sum[10+y]+=v;
    else kong[x] ++, kong[10+y]++,sum[x]+=v,sum[10+y]+=v;
    for(auto as: rm[id]) {
        px = (as-1)/10+1, py = as % 10;
        py = (py==0?10:py);
        nd[px][py] -= v;
        if(v < 0) bl[px][py] += 1;
        else bl[px][py] -= 1;
    }
}
void dfs(int now, int remain) {
    if(remain == 0) {
        flag = 1;
        return;
    }
    if(flag) return ;
    int x = (vs[now]-1)/10+1, y = vs[now] % 10;
    y = (y==0?10:y);
    for(int i = 1; i <= 3; ++i) {
        if(check(x, y, i)) {
            ans[x][y] = i;
            gao(x, y, i);
            dfs(now+1, remain-1);
            if(flag) return ;
            gao(x, y, -i);
        }
    }
}
int main() {
    int tim; scanf("%d", &tim);
    while(tim --) {
        scanf("%d", &m);
        memset(bl, 0, sizeof(bl));
        memset(nd, 0, sizeof(nd));
        memset(kong, 0, sizeof(kong));
        memset(sum, 0, sizeof(sum));
        flag = 0;
        for(int i = 0; i <= 101; ++i) rm[i].clear();
        vs.clear();
        printf("%d\n", m);
        for(int i = 1; i <= 10; ++i) for(int j = 1; j <= 10; ++j) scanf("%d", &ar[i][j]),ans[i][j]=ar[i][j];
        for(int i = 1; i <= 10; ++i) {
            for(int j = 1; j <= 10; ++j) {
                nd[i][j] = ar[i][j];
                if(ar[i][j] == -1) {
                    ++ kong[i];
                    ++ kong[10+j];
                    vs.push_back((i-1)*10+j);
                    for(int h = 0, px, py; h < 8; ++h) {
                        px = i + dir[h][0], py = j + dir[h][1];
                        if(px < 1 || py < 1 || px > 10 || py > 10) continue;
                        if(ar[px][py] != -1) {
                            rm[(i-1)*10+j].push_back((px-1)*10+py);
                        }
                    }
                }else {
                    for(int h = 0, px, py; h < 8; ++h) {
                        px = i + dir[h][0], py = j + dir[h][1];
                        if(px < 1 || py < 1 || px > 10 || py > 10) continue;
                        if(ar[px][py] == -1) ++ bl[i][j];
                    }
                }
            }
        }
        n = vs.size();
        dfs(0, n);
        for(int i = 1; i <= 10; ++i) {
            for(int j = 1; j <= 10; ++j) {
                assert(ans[i][j] != -1);
                if(ar[i][j] == -1) continue;
                int tmp = 0;
                for(int h = 0, px, py; h < 8; ++h) {
                    px = i + dir[h][0], py = j + dir[h][1];
                    if(px < 1 || py < 1 || px > 10 || py > 10) continue;
                    if(ar[px][py] == -1) tmp += ans[px][py];
                }
                assert(ans[i][j] == ar[i][j]);
                assert(tmp == ar[i][j]);
            }
        }
        for(int i = 1; i <= 10; ++i) {
            for(int j = 1; j < 10; ++j) printf("%d ", ans[i][j]);
            printf("%d\n", ans[i][10]);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值