NOIP多校联考7

来自世间,一对平凡的夫妻身旁;来自昨天,谁以青春赴万丈理想?

我是寸土不让的家乡啊,我是永不低头的倔强啊,接过万千热血的初衷,当有对答世界的音量!

A.计算器(calc)

依然不知道为什么会错,但是先按正解改一下好了……

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 105;
const ll mod = 1e9 + 7;
const int INF = 0x7ffffff;

int n, k, cnt[maxn], ma, mb, mc, md;
ll Max;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

struct node 
{
    int id, a, b, c, d;
    bool operator < (const node &T) const 
    {
        return id < T.id;
    }
}p[maxn];

ll query(int a, int b, int c, int d)
{
    return (ll)(100+a)*(100+b)*(100+c)*(100+d);
}

int main()
{
    n = read(); k = read();
    for(int i=1; i<=n; i++)
    {
        p[i].id = read(); p[i].a = read(); p[i].b = read();
        p[i].c = read(); p[i].d = read();
        cnt[p[i].id]++;
    }
    sort(p+1, p+1+n);
    for(int i=1; i<=k; i++)
    {
        cnt[i] += cnt[i-1];
    }
    for(int i=1; i<=k; i++)
    {
        int ha = ma, hb = mb, hc = mc, hd = md;
        for(int j=cnt[i-1]+1; j<=cnt[i]; j++)
        {
            int a = ma+p[j].a, b = mb+p[j].b, c = mc+p[j].c, d = md+p[j].d;
            ll res = query(a, b, c, d);
            if(res > Max)
            {
                Max = res;
                ha = a; hb = b; hc = c; hd = d;
            }
        }
        ma = ha; mb = hb; mc = hc; md = hd;
    }
    printf("%lld", Max);
    
    return 0;
}
WA 60eps

感谢能指出以上代码问题的大佬***%%%

抄完正解依然觉得自己毫无问题&%¥#@无可救药了

update:感觉好像错在了每个部位都取最大值不一定构成整体最大值,也就是不能分步贪心。顺便说一下dfs里的优化:记录即将跳到的位置,也就是cnt=0的根本就不展开成搜索树,不这样做的话好像会TLE80或90(同学的经验)

***如果问题不是我想到的这个,依然期待可以收到找到以上代码问题的大佬的评论***

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 105;
const ll mod = 1e9 + 7;
const int INF = 0x7ffffff;

int n, m, x, cnt[maxn], e[maxn][maxn][4], nxt[maxn];
ll ans;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

void dfs(int x, int a, int b, int c, int d)
{
    if(x > m)
    {
        ll tmp = (ll)a*b*c*d;
        if(tmp > ans) ans = tmp;
        return;
    }
    int num = cnt[x];
    if(!num)
    {
        dfs(nxt[x], a, b, c, d);
        return;
    }
    for(int i=1; i<=num; i++)
    {
        dfs(x+1, a+e[x][i][0], b+e[x][i][1], c+e[x][i][2], d+e[x][i][3]);
    }
}

int main()
{
    //freopen("calc2.in", "r", stdin);
    
    n = read(); m = read();
    while(n--)
    {
        x = read();
        cnt[x]++;
        for(int j=0; j<4; j++) e[x][cnt[x]][j] = read();
    }
    x = m + 1;
    for(int i=m; i>=1; i--)
    {
        nxt[i] = x;
        if(cnt[i]) x = i;
    }
    ans = 0;
    dfs(1, 100, 100, 100, 100);
    printf("%lld\n", ans);
    
    return 0;
}
View Code

B.对称轴(symmetry)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 2e5 + 3;
const ll mod = 1e9 + 7;
const int INF = 0x7ffffff;

int T, n, ans;
double x_1, y_1;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

struct node 
{
    int x, y;
}p[maxn];

double get_k(double x_1, double y_1, double x_2, double y_2)
{
    if(x_1 == x_2) return 1.0*INF;
    if(y_1 == y_2) return 0.0;
    return (y_1-y_2) / (x_1-x_2);
}

bool check(int l, int r, int a, int b, int k)
{
    while(l > a && r > b)
    {
        double x_3 = (p[l].x+p[r].x)/2.0, y_3 = (p[l].y+p[r].y)/2.0;
        double k2 = get_k(x_1, y_1, x_3, y_3);
        l--; r++;                     
        if(abs(k-k2) > 1e-6) return 0;
    }
    return 1;
}

bool check2(int l, int r, int k)
{
    while(l < r)
    {
        double x_3 = (p[l].x+p[r].x)/2.0, y_3 = (p[l].y+p[r].y)/2.0;
        double k2 = get_k(x_1, y_1, x_3, y_3);
        l++; r--;
        if(abs(k-k2) > 1e-6) return 0;
    }
    return 1;
}

bool check3(int l, int r, int k)
{
    while(l < r)
    {
        double x_3 = (p[l].x+p[r].x)/2.0, y_3 = (p[l].y+p[r].y)/2.0;
        double k2 = get_k(x_1, y_1, x_3, y_3);
        l++; r--;
        if(abs(k-k2) > 1e-6) return 0;
    }
    double x_3 = p[l].x, y_3 = p[l].y;
    double k2 = get_k(x_1, y_1, x_3, y_3);
    if(abs(k-k2) > 1e-6) return 0;
    return 1;
}

double get_len(double x_1, double y_1, double x_2, double y_2)
{
    return (x_1-x_2)*(x_1-x_2)+(y_1-y_2)*(y_1-y_2);
}

int main()
{
    T = read();
    while(T--)
    {
        n = read(); ans = 0;
        for(int i=1; i<=n; i++)
        {
            p[i].x = read(); p[i].y = read();
            p[n+i].x = p[i].x; p[n+i].y = p[i].y;
        }
        if(n & 1)
        {
            for(int i=1; i<=n/2; i++)
            {
                int j = i+n-1;
                int lmax = (i+j)>>1, rmin = lmax+1;
                x_1 = p[i].x, y_1 = p[i].y;
                int l = lmax, r = rmin;
                double x_2 = (p[l].x+p[r].x)/2.0, y_2 = (p[l].y+p[r].y)/2.0;
                if(get_len(x_1, y_1, p[l].x, p[l].y) != get_len(x_1, y_1, p[r].x, p[r].y))
                {
                    continue;
                }
                double k = get_k(x_1, y_1, x_2, y_2);
                l--; r++;
                if(check(l, r, i, i+n, k)) ans++;
            }
        }
        else 
        {
            for(int i=1; i<=n/2; i++)
            {
                int j = i+n-1;
                int l = i, r = j;
                x_1 = (p[l].x+p[r].x)/2, y_1 = (p[l].y+p[r].y)/2;
                l++; r--;
                double x_2 = (p[l].x+p[r].x)/2.0, y_2 = (p[l].y+p[r].y)/2.0;
                double k = get_k(x_1, y_1, x_2, y_2);
                l++; r--;;
                if(check2(l, r, k)) ans++;
            }
            for(int i=1; i<=n/2; i++)
            {
                int j = i+n;
                int l = i, r = j;
                x_1 = p[l].x, y_1 = p[l].y;
                l++; r--;
                double x_2 = (p[l].x+p[r].x)/2.0, y_2 = (p[l].y+p[r].y)/2.0;
                if(get_len(x_1, y_1, p[l].x, p[l].y) != get_len(x_1, y_1, p[r].x, p[r].y))
                {
                    continue;
                }
                double k = get_k(x_1, y_1, x_2, y_2);
                l++; r--;
                if(check3(l, r, k)) ans++;
            }
        }
        printf("%d\n", ans);
    }
    
    return 0;
}
赛时TLE 20eps

就是直接枚举对称轴的直线斜率。。我也不知道我为什么心血来潮的想调它,就调了3个小时。。。

结果就是T3和T4没时间审题了。。。  有人能暴力出80分,有人暴力能AC,果然我是个蒟蒻。

至于正解:(一个图形旋转一个小于180°的角,能够和自己重合几次,就有几条对称轴)

好像上面那句话有点无关,不过似乎可以提供一些灵感,那就是依次记录多边形边的长度和角的大小,把这道题转化成字符串。因为变长带根号,角也不好求(据说算三角函数常数很大),就考虑一种简洁的记录方式——用边长的平方表示边长,用向量的叉积表示角度(这个正解想不出来不能怪我,叉积还没学呢,谁知道它还有这种用途!),实数环就变成了整数环,and then 问题就成了:环上有几个位置,满足环从这里断开后,可以得到一条回文链?

match数组记录这条实数环,为了枚举断点所以要两倍长度,pattern数组是这个实数环的“反环”(内容相同方向相反),用KMP算法不断将match和pattern进行字符串匹配,这就比较板子,可惜我忘了……

叉积公式(abcd什么的就是坐标表示的向量的坐标啊,居然还花了好几分钟理解这个式子)(a, b) × (c, d) = ad - bc

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 2e5 + 3;
const ll mod = 1e9 + 7;
const int INF = 0x7ffffff;

#define sqr(x) ((x)*(x))
int T, n, tot, ans, x[maxn], y[maxn], pattern[maxn], match[maxn<<1];
int nxt[maxn<<1];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int main()
{
    //freopen("sym2.in", "r", stdin);
    
    T = read();
    while(T--)
    {
        n = read();
        for(int i=1; i<=n; i++)
        {
            x[i] = read(); y[i] = read();
        }
        x[n+1] = x[1], y[n+1] = y[1], x[n+2] = x[2], y[n+2] = y[2];
        tot = 0; ans = 0;
        for(int i=1; i<=n; i++)
        {
            match[++tot] = sqr(x[i+1]-x[i])+sqr(y[i+1]-y[i]);
            match[++tot] = (x[i+1]-x[i])*(y[i+2]-y[i])-(y[i+1]-y[i])*(x[i+2]-x[i]);
        }
        for(int i=1; i<=tot; i++)
        {
            pattern[tot-i+1] = match[i+tot] = match[i];
        }
        memset(nxt, 0, sizeof(nxt));
        for(int i=2,j=0; i<=tot; i++)
        {
            while(j && pattern[j+1]!=pattern[i]) j = nxt[j];
            nxt[i] = (j+=(pattern[j+1]==pattern[i]));
        }
        for(int i=1,j=0; i<=(tot<<1); i++)
        {
            while(j && pattern[j+1]!=match[i]) j = nxt[j];
            j += (pattern[j+1]==match[i]);
            if(j == tot) ans++, j=nxt[j];
        }
        printf("%d\n", ans);
    }
    
    return 0;
}
View Code

D.签到题(qiandao)

我没到,,或者说,,我迟到了

知道了规律是什么还要开一个vector TLE70,我对我自己真是无语了。。。分明是桶就能解决的问题

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 1e6 + 3;
const ll mod = 1e9 + 7;
const int INF = 0x7ffffff;

int n, m, c, k, ans;
int a[maxn];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int main()
{
    //freopen("qiandao4.in", "r", stdin);
    
    n = read(); m = read(); k = read(); c = read();
    for(int i=1; i<=k; i++)
    {
        int x = read(), y = read();
        a[x]++; a[y+n]++;
    }
    for(int i=1; i<=n+m; i++)
    {
        if(a[i]%c) ans++;
    }
    printf("%d\n", ans);
    
    return 0;
}
View Code

 

posted @ 2022-07-28 14:50  Catherine_leah  阅读(27)  评论(0编辑  收藏  举报
/* */