2019.10.03解题报告

总体来说能打的暴力都打了
期望\(100 + 40 + 30 = 170\)
实际\(100 + 40 + 10 = 180\)
数据良心(其实是数据太水惹

T1

第一眼觉得就是要找规律,然后直接找找不出来,所以用暴力搜一下

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

const int N = 2011;

int vis[N][N];

struct node {
    int x, y, num;
};

const int dx[8] = {-2,-2,-1,1,2,2,1,-1};
const int dy[8] = {-1,1,2,2,1,-1,-2,-2};

queue <node> q;

int sum = 0;

int main() {
    for(int T = 0; T <= 100; T++) {
        int n = T;
        sum = 0;
        memset(vis, 0, sizeof(vis));
        while(!q.empty()) q.pop();
        node st;
        st.x = 1000;
        st.y = 1000;
        vis[st.x][st.y] = 1;
        st.num = 0;
        q.push(st);
        while(!q.empty()) {
            node top = q.front();
            q.pop();
            sum++;
            for(int i = 0; i < 8; i++) {
                node tmp;
                tmp.x = top.x + dx[i];
                tmp.y = top.y + dy[i];
                tmp.num = top.num + 1;
                if(!vis[tmp.x][tmp.y] && tmp.x >= 0 && tmp.y >= 0 && tmp.x <= 2000 && tmp.y <= 2000 &&tmp.num <= n) {
                    vis[tmp.x][tmp.y] = tmp.num;
                    q.push(tmp);
                }
            }
        }
        cout  << sum << '\n';
    }
}

找不到什么规律,于是求一下差值,还是没什么规律,用差值再求一下差值,发现前五项的差值是特别的,所以直接特别输出,其他的发现差值恒定为\(28\),规律就找到啦

\(if(n > 5)\ n \ \ -= 4\)

\(a\)数组表示原数列
\(a[1] = 325\)
\(a[2] = 473\)
\(a[3] = 649\)
\(a[4] = 853\)
\(a[5] = 1085\)

\(b\)数组表示差
\(b[1] = 148\)
\(b[2] = 176\)
\(b[3] = 204\)
\(b[4] = 232\)
\(.................\)
\(b[n] = 120 + n * 28\)

显然
\(b[2] = b[1] + 28\)
\(b[3] = b[2] + 28\)
\(....................................\)
\(b[n] = b[n - 1] + 28\)


\(a[2] - a[1] = b[1]\)
\(a[3] - a[2] = b[2]\)
\(a[4] - a[3] = b[3]\)
\(a[5] - a[4] = b[4]\)
\(.............................\)
\(a[n] - a[n - 1] = b[n - 1]\)

加起来
\(a[2] - a[1] + a[3] - a[2] + a[4] - a[3] + .......... a[n] - a[n - 1] = b[1] + b[2] + b[3] + ......... b[n - 1]\)

去掉多余项,得
\(a[n] - a[1] = \sum_{i = 1}^{n - 1} b[i]\)
设\(x = \sum_{i = 1}^{n - 1} b[i]\)

所以\(a[n] = x + a[1]\)
x是个等差数列,然后等差数列求和公式为\(\frac{首项 + 尾项}{2} *数量\)

这里就是\(\frac{b[1] + b[n - 1]}{2} *(n - 1)\)

所以就是\(\frac{b[1] + b[n - 1]}{2} *(n - 1) + a[1]\)

就等于\(\frac{120 + 28 + 120 + 28 * (n - 1)}{2} *(n - 1) + 325\)

然后化简一下,可能爆\(long\ long\),保险起见用\(unsigned\ long\ long\),然后就做完了

//知识点:宽搜打表找规律
/*
By:Loceaner
找到神奇规律之后发现是等差数列……
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#define ull unsigned long long
using namespace std;

int T;
ull n;
ull a[5] = {1, 9, 41, 109, 205};

int main() {
    freopen("horse.in", "r", stdin);
    freopen("horse.out", "w", stdout);
    scanf("%d", &T);
    while(T--) {
        cin >> n;
        if(n < 5) {
            cout << a[n] << "\n";
            continue;
        }
        else {
            n -= 4;
            ull ans = 120 * (n - 1) + 14 * n * (n - 1) + 325;
//          ull ans = (240 + 28 * n) / 2 * (n - 1) + 325;
            cout << ans << '\n';
        }
    }
    return 0;
}

T2

很显然,第一问的答案就是 \(2^n\)。
第二问的话。。到现在也不会
然后dsr聚聚给我讲了半年,我也不会,上聚聚的代码

#include <bits/stdc++.h>
using namespace std;
const int _=1e5+7;
int n,len,k,vis[_],ans[_];
int main() {
    freopen("sensor.in","r",stdin);
    freopen("sensor.out","w",stdout);
    cin>>k;n=1<<k;
    vis[0]=1;
    for(int i=n-k+1;i<=n;++i) ans[i]=1;
    for(int i=0;i<k;++i) vis[n-(1<<i)]=1;
    for(int i=k+1,jt=0;i<=n-k;++i) {
        jt=(jt<<1)&(n-1);
        if(vis[jt]) ans[i]=1,jt|=1;
        vis[jt]=1;
    }
    printf("%d ",n);
    for(int i=1;i<=n;++i) printf("%d",ans[i]);
    return 0;
}

T3

第一眼觉得是线段树,因为一列的话挺好操作,可是有十五列,开十五个线段树??

懵逼了

再加上没有时间写了,于是果断写了暴力,拿了40

下面是40分暴力和修改过的满分代码

//暴力啦啦啦
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

inline int read() {
    char c = getchar();
    int x = 0, f = 1;
    for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    return x * f;
}

int r, c, q;
char a[50011][20];
char b[50011][20];

int main() {
    freopen("holiday.in", "r", stdin);
    freopen("holiday.out", "w", stdout);
    r = read(), c = read(), q = read();
    for(int i = 1; i <= r; i++) {
        scanf("%s",a[i]+1);
    }
    for(int i = 1; i <= r; i++) {
        for(int j = 1; j <= c; j++) {
            b[i][j] = '0';
        }
    }
    while(q--) {
        int cnt = 0;
        int u1 = read(), v1 = read(), u2 = read(), v2 = read();
        char col;
        cin >> col;
        for(int i = u1; i <= v1; i++) {
            for(int j = u2; j <= v2; j++) {
                b[i][j] = col;
            }
        }
        for(int i = 1; i <= r; i++) {
            for(int j = 1; j <= c; j++) {
                if(a[i][j] == b[i][j]) cnt++;
            }
        }
        cout << cnt << '\n';
    }
    return 0;
}

修改后

//知识点:多个线段树
/*
By:Loceaner
第一眼线段树,第二眼不会打
第三眼打暴力,最后多了10分
数据良心
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 5e4 + 11;

inline int read() {
    char c = getchar();
    int x = 0, f = 1;
    for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    return x * f;
}

char a[N][20];
int r, c, q;

#define lson rt << 1
#define rson rt << 1 | 1

struct seg_tree{
    struct node {
        int siz, tot, ans, tag;
    } t[N << 2];

    void build(int l, int r, int rt, int k) {
        t[rt].tag = -1;
        t[rt].siz = r - l + 1;
        if(l == r) {
            t[rt].tot = (a[l][k] == '1');
            t[rt].ans = (a[l][k] == '0');
            return;
        }
        int mid = (l + r) >> 1;
        build(l, mid, lson, k);
        build(mid + 1, r, rson, k);
        t[rt].tot = t[lson].tot + t[rson].tot;
        t[rt].ans = t[lson].ans + t[rson].ans;
    }

    void tag(int rt, int ad) {
        if(ad == 1) t[rt].ans = t[rt].tot;
        else t[rt].ans = t[rt].siz - t[rt].tot;
        t[rt].tag = ad;
    }

    void pushdown(int rt) {
        if(t[rt].tag != -1) {
            tag(lson, t[rt].tag);
            tag(rson, t[rt].tag);
            t[rt].tag = -1;
        }
    }

    void update(int L, int R, int k, int l, int r, int rt) {
        if(L <= l && r <= R) {
            tag(rt, k);
            return;
        }
        pushdown(rt);
        int mid = (l + r) >> 1;
        if(L <= mid) update(L, R, k, l, mid, lson);
        if(R > mid) update(L, R, k, mid + 1, r, rson);
        t[rt].ans = t[lson].ans + t[rson].ans;
    }
} T[16];

int main() {
    freopen("holiday.in", "r", stdin);
    freopen("holiday.out", "w", stdout);
    r = read(), c = read(), q = read();
    for(int i = 1; i <= r; i++) scanf("%s", a[i] + 1);
    for(int i = 1; i <= c; i++) T[i].build(1, r, 1, i);
    while(q--) {
        int L = read(), R = read(), u2 = read(), v2 = read(), col = read();
        for(int i = u2; i <= v2; i++) T[i].update(L, R, col, 1, r, 1);
        int ans = 0;
        for(int i = 1; i <= c; i++) ans += T[i].t[1].ans;
        cout << ans << '\n';
    }
    return 0;}

原文地址:https://www.cnblogs.com/loceaner/p/11620647.html

时间: 2024-09-30 12:24:08

2019.10.03解题报告的相关文章

2019.10.03考试报告

10min:打完T1,为了不滑天下之大稽,打了一个对拍 50min:打完了T2T3的暴力,准备推一推T2. 2h:打完T3的正解和对拍. 3h:T3写了一个O(n*log2(n)*log2(n))的40分算法. 最后调T3的60分线段树调到考试结束也没过对拍. 期望分数:240 实际得分:200 就是因为这一个智障级的错误! 题解: T1 对于每个a[i],O(sqrt(a[i]))预处理出ta的所有约数,用map或hashmap存起来即可. T2 把商品和询问离线并按时间排序,枚举时间,是商品

2019.10.02考试报告

T1 一般都能想到二分+取前m大正值,但是复杂度无法承受,我们发现要的是sum值,并不需要每个位置的准确值, 所以用可以nth_element把大于第m大的放右边即可.(原来nth还可以这么用). nth_element实现: 每次找一个base,小于base的放右边,大于的放右边 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e8+10; 4 int n,k,a[N]; 5 inline int read()

2019.10.08考试报告

T1 用一个堆维护最小的是谁,每次加入一个值x时查询堆顶是否小于x,有则买top卖x,之后分为是不是反悔操作判断要不要把pop. 然而好像其他人都push两个来进行反悔操作. 1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<queue> 6 #define int long long 7 using namespace

2019 icpc 徐州 解题报告

A.Cat 题库链接 给定区间[l,r],求一个最长子区间,使得区间异或和小于等于s,(结论)偶数和偶数后三个数的异或和等于0 #include <bits/stdc++.h> using namespace std; #define mem(a,b) memset(a,b,sizeof(a)) #define cin(a) scanf("%d",&a) #define pii pair<int,int> #define ll long long #de

10.2解题报告

题目一:栈的优化 原代码:运用函数递归 由于我们知道火车出来的个数与火车总共的个数一定是一样的,所以可以用0 1来表示车辆的出入. 例如:101100 就表示进出进进出出,也就为132. 我们用ruv来表示进入的车子数,chuv表示出来的车子数,当chuv和ruv都等于撤资总数时,我们就找到了一种排列方法.当ruv小于n时,说明已经进去的车子数没到n节,还有空间继续进入车辆,我们可以写作 if(ruv<n) dfs(ruv+1,chuv);我们要保证出去的车子比进来的车子少,这样才可以符合实际的

10.15解题报告

D:[基本算法-贪心算法]删数问题 描述 键盘输入一个高精度的正整数n(<=240位),去掉其中任意s个数字后剩下的数字按原左右次序将组成一个新的正整数.编程对给定的n和s,寻找一种方案,使得剩下的数字组成的新数最小. 这道题目我们可以用贪心法则来攻克 既然要每次删除一个数,那我们就需要让每一次都做出一个最好的选择,这样最后我们也就会得到最佳方案 如何每一次都作出最好的选择,也就是每一次都删除第一个比后面数字大得数,因为如果n比n-1大的话,后面再出现此类情况,我们可以保证n在最大的数位上,于是

解题报告 smoj 2019初二创新班(2019.3.17)

目录 解题报告 smoj 2019初二创新班(2019.3.17) T1:找玩具 题目描述 题意转化 分析 代码 优化(代码复杂度) T2:闯关游戏 题目描述 分析 代码 T3:子数组有主元素 题目描述 分析 代码(\(O(nm\log n)\)) 优化 代码(\(O(nm)\)) 解题报告 smoj 2019初二创新班(2019.3.17) 时间:2019.3.21 T1:找玩具 题目描述 在游戏开始之前,游戏大师在房间的某些地方隐藏了N个玩具.玩具编号为1到N.您的任务是尽可能多地找到这些玩

2019模拟赛09场解题报告

目录 2019模拟赛09场解题报告 目录la~~ 题一:瞬间移动 题二:食物订购 题三:马蹄印 题四:景观美化 2019模拟赛09场解题报告 标签(空格分隔): 解题报告 Forever_chen 2019.8.20 目录la~~ 题一:瞬间移动 [题面] 有一天,暮光闪闪突然对如何将一个整数序列a1,a2,...,an排序为一个不下降序列起了兴趣.身为一只年轻独角兽的她,只能进行一种叫做"单元转换"(unit shift)的操作.换句话说,她可以将序列的最后一个元素移动到它的起始位置

2020-3-14 acm训练联盟周赛Preliminaries for Benelux Algorithm Programming Contest 2019 解题报告+补题报告

2020-3-15比赛解题报告+2020-3-8—2020-3-15的补题报告 2020-3-15比赛题解 训练联盟周赛Preliminaries for Benelux Algorithm Programming Contest 2019  A建筑(模拟) 耗时:3ms 244KB 建筑 你哥哥在最近的建筑问题突破大会上获得了一个奖项 并获得了千载难逢的重新设计城市中心的机会 他最喜欢的城市奈梅根.由于城市布局中最引人注目的部分是天际线, 你的兄弟已经开始为他想要北方和东方的天际线画一些想法