NOIP多校联考9

A.理想路径

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 2003;
const ll mod = 20040820;
const int INF = 2147483647;
const int lim = 1e4 + 1;

int n, m, q, dfn[maxn<<1], tot;
bool a[maxn][maxn], flag, vis[maxn], tag;
vector<int> son[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;
}

void dfs(int x, int y)
{
    if(vis[x]) 
    {
        flag = 1; return;
    }
    if(!flag && !tag) dfn[++tot] = x;
    if(x == y)
    {
        tag = 1; return;
    }
    vis[x] = 1;
    for(int i=0; i<son[x].size(); i++)
    {
        int v = son[x][i];
        dfs(v, y);
        if(flag || tag) return;
    }
    if(!flag && !tag) dfn[++tot] = x;
}

int main()
{
    //freopen("tiao.txt", "r", stdin);
    
    n = read(); m = read(); q = read();
    for(int i=1; i<=m; i++)
    {
        int x = read(), y = read();
        a[x][y] = 1;
        son[x].push_back(y);
    }
    for(int i=1; i<=n; i++)
    {
        sort(son[i].begin(), son[i].end());
    }
    for(int k=1; k<=n; k++)
    {
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
            {
                if(a[i][k] && a[k][j])
                {
                    a[i][j] = 1;
                }
            }
        }
    }
    /*printf("\n\n");
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }
    printf("\n\n");*/
    while(q--)
    {
        int x = read(), y = read(), k = read();
        if(x == y)
        {
            if(k == 1)
            {
                printf("%d\n", x); continue;
            }
            else 
            {
                printf("-1\n"); continue;
            }
        }
        if(!a[x][y]) 
        {
            printf("-1\n"); continue;
        }
        flag = 0; tag = 0; tot = 0;
        memset(vis, 0, sizeof(vis));
        memset(dfn, 0, sizeof(dfn));
        dfs(x, y);
        if(tot < k || flag)
        {
            printf("-1\n"); continue;
        }
        else 
        {
            /*printf("x = %d y = %d\n", x, y);
            for(int i=1; i<=tot; i++)
            {
                printf("%d ", dfn[i]);
            }
            printf("\n\n");*/
            printf("%d\n", dfn[k]);
        }
    }
    
    return 0;
}
TLE 30

每个问题跑一遍dfs,sort vector的灵感好像和[NOIP2018]旅行类似?

 ---插入:旅行:n=m的情况一定有一条环上的边不走,所以可以暴力枚举删掉哪条边,这个操作的dfs不错哦,至于怎么判断字典序的大小,直接在数组里暴力判断就好了(hash什么的想多了)。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 5e3 + 2;
const ll mod = 998244353;
const int INF = 2147483647;
const int lim = 1e4 + 1;

int n, m, ans[maxn], res[maxn], u1[maxn<<1], v1[maxn<<1], cnt;
int du, dv, tot, cir[maxn];
bool flag, vis[maxn];
vector<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;
}

struct Edge 
{
    int from, to;
}e[5010];

//找出环,把环上的变压进数组里
void dfs3(int x, int fa)
{
    vis[x] = 1;
    for(int i=0; i<a[x].size(); i++)
    {
        int to = a[x][i];
        if(to == fa) continue;
        if(vis[to])
        {
            flag = 1;
            cir[to] = 1;
            cir[x] = 1;
            u1[++cnt] = x; v1[cnt] = to;
            return;
        }
        dfs3(to, x);
        if(flag && cir[to])
        {
            if(cir[x])
            {
                flag = 0;
                u1[++cnt] = x; v1[cnt] = to;
                return;
            }
            else 
            {
                cir[x] = 1;
                u1[++cnt] = x; v1[cnt] = to;
                return;
            }
        }
    }
}

void dfs1(int u, int fa)
{
    if(vis[u]) return;
    vis[u] = 1;
    res[++tot] = u;
    for(int i=0; i<a[u].size(); i++)
    {
        int v = a[u][i];
        if(v == fa) continue;
        if((u==du&&v==dv)||(u==dv&&v==du)) continue;
        dfs1(v, u);
    }
}

int check()
{
    for(int i=1; i<+n; i++)
    {
        if(res[i] < ans[i]) return 1;
        else if(res[i] > ans[i]) return 0;
    }
    return 0;
}

void update()
{
    for(int i=1; i<=n; i++)
    {
        ans[i] = res[i];
    }
}

void dfs2(int u, int fa)
{
    ans[++tot] = u;
    for(int i=0; i<a[u].size(); i++)
    {
        int v = a[u][i];
        if(v == fa) continue;
        dfs2(v, u);
    }
}

int main()
{
    n = read(); m = read();
    for(int i=1; i<=m; i++)
    {
        int x = read(), y = read();
        a[x].push_back(y);
        a[y].push_back(x);
        e[i].from = x; e[i].to = y;
    }
    for(int i=1; i<=n; i++)
    {
        sort(a[i].begin(), a[i].end());
    }
    if(m == n)
    {
        dfs3(1, 0);
        flag = 1;
        for(int i=1; i<=cnt; i++)
        {
            du = u1[i]; dv = v1[i];
            memset(vis, 0, sizeof(vis));
            tot = 0;
            dfs1(1, 0);
            if(tot < n) continue;
            if(flag)
            {
                update(); flag = 0;
            }
            if(check())
            {
                update();
            }
        }
        for(int i=1; i<=n; i++)
        {
            printf("%d ", ans[i]);
        }
    }
    else 
    {
        dfs2(1, 0);
        for(int i=1; i<=n; i++)
        {
            printf("%d ", ans[i]);
        }
    }
    
    return 0;
}
旅行

--come back:我不知道这题怎么离线啊……(⊙o⊙)…

B.第一题

相乘等于完全平方数?n*m暴力枚举……

(同学的经验,提交的代码中如果出现了srand(time(0))会因为运行错误爆0,尽管你可能并没有应用随机数……)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 2e6 + 3;
const ll mod = 20040820;
const int INF = 2147483647;
const int lim = 1e4 + 1;

int n, m, cnt[maxn], p;
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;
}

int main()
{
    //freopen("one.in", "r", stdin);
    
    n = read(); m = read();
    if(n > m) swap(n, m);
    p = sqrt(m);
    for(int i=1; i<=p; i++)
    {
        cnt[i*i] = 1;
    }
    for(int i=2; i<=m; i++)
    {
        cnt[i] += cnt[i-1];
    }
    ans = n-cnt[n];
    ans += cnt[n] * cnt[m];
    printf("%lld\n", ans);
    
    return 0;
}
TLE 20

 这叫什么?按照100的正解改却T了个30!?据说按照n方暴力加个大样例的特判都能水个30……

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 2e6 + 3;
const ll mod = 20040820;
const int INF = 2147483647;
const int lim = 1e4 + 1;

int v[maxn], prime[maxn], n, m, cnt[maxn], ans, hav[maxn], num, tot;

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 primes(int n)
{
    for(int i=2; i<=n; i++)
    {
        if(v[i] == 0) 
        {
            v[i] = i; prime[++tot] = i;
        }
        for(int j=1; j<=tot; j++)
        {
            if(prime[j]>v[i] || prime[j]*i > n) break;
            v[i*prime[j]] = prime[j];
        }
    }
}

int main()
{
    n = read(); m = read();
    if(n > m) swap(n, m);
    primes(n);
    
    for(int i=1; i<=n; i++)
    {
        memset(cnt, 0, sizeof(cnt));
        memset(hav, 0, sizeof(hav));
        int f = i; num = 0;
        while(f && v[f])
        {
            cnt[v[f]]++;
            if(hav[num] != v[f]) hav[++num] = v[f];
            f /= v[f];
        }
        int t = 1;
        for(int j=1; j<=num; j++)
        {
            if(cnt[hav[j]] & 1)
            {
                t *= hav[j];
            }
        }
        int g = m/t;
        ans += sqrt(g);
    }
    
    printf("%d\n", ans);
    
    return 0;
}
TLE 30

统计个数和统计乘积可以是一步操作啊!两个memset和为了判断新的来个循环不T才怪

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 2e6 + 3;
const ll mod = 20040820;
const int INF = 2147483647;
const int lim = 1e4 + 1;

int v[maxn], prime[maxn], n, m, ans, num, tot;

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 primes(int n)
{
    for(int i=2; i<=n; i++)
    {
        if(v[i] == 0) 
        {
            v[i] = i; prime[++tot] = i;
        }
        for(int j=1; j<=tot; j++)
        {
            if(prime[j]>v[i] || prime[j]*i > n) break;
            v[i*prime[j]] = prime[j];
        }
    }
}

int main()
{
    n = read(); m = read();
    if(n > m) swap(n, m);
    primes(n);
    
    for(int i=1; i<=n; i++)
    {
        int f = i, t = 1; num = 0;
        while(f && v[f])
        {
            int cnt = 0, zs = v[f];
            while(f && (f%zs==0)) cnt++, f/=zs;
            if(cnt&1) t *= zs;
        }
        int g = m/t;
        ans += sqrt(g);
    }

    printf("%d\n", ans);
    
    return 0;
}
View Code

C.消除贫困

我居然AC了?!由于过程不重要,离线处理一下问题(一开始我还想用线段树来着……)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 2e5 + 3;
const ll mod = 20040820;
const int INF = 2147483647;
const int lim = 1e4 + 1;

int n, a[maxn], v[maxn], Max2, qes;

struct node 
{
    int f, x, y;
}q[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("welloff.in", "r", stdin);
    //freopen("tiao.txt", "w", stdout);
    
    n = read();
    for(int i=1; i<=n; i++)
    {
        a[i] = read();
    }
    qes = read();
    for(int i=1; i<=qes; i++)
    {
        q[i].f = read();
        if(q[i].f == 1)
        {
            q[i].x = read(); q[i].y = read();
        }
        else 
        {
            q[i].x = read();
        }
    }
    for(int i=qes; i>=1; i--)
    {
        if(q[i].f == 1)
        {
            if(!v[q[i].x] && q[i].y>Max2)
            {
                v[q[i].x] = q[i].y;
                //printf("v[%d] = %d\n", q[i].x, v[q[i].x]);
            }
            else if(!v[q[i].x] && q[i].y<=Max2)
            {
                v[q[i].x] = Max2;
                //printf("v[%d] = %d\n", q[i].x, v[q[i].x]);
            }
        }
        else 
        {
            Max2 = max(Max2, q[i].x);
            //printf("Max2 = %d\n", Max2);
        }
    }
    for(int i=1; i<=n; i++)
    {
        if(v[i])
        {
            printf("%d ", v[i]);
        }
        else 
        {
            printf("%d ", max(a[i], Max2));
        }
    }
    printf("\n");
    
    return 0;
}
View Code

D.数串

只会n=1和m=0的magic dfs... 可以重复的dfs想了好久,高精度加法调了半天最后发现n<=6的数据范围完全没必要,用得着的数据范围dfs会被T飞……

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 605;
const ll mod = 20040820;
const int INF = 2147483647;
const int lim = 1e4 + 1;

int n, m, k, b[maxn], c[maxn], ans[maxn], num;
bool v[maxn][maxn];

struct node 
{
    int a, b;
}p[107];

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 add(int a[], int b[], int c[])
{
    num = max(n, num);
    int x = 0;
    for(int i=1; i<=num; i++)
    {
        c[i] = a[i] + b[i] + x; x = 0;
        x = c[i]/10;
        c[i] %= 10;
    }
    if(x) c[++num] = x;
}

void dfs(int a, int n)
{
    if(a > n)
    {
        add(b, c, ans);
        for(int i=1; i<=num; i++)
        {
            c[i] = ans[i];
            ans[i] = 0;
        }
        return;
    }
    for(int i=1; i<=k; i++)
    {
        if(v[a][i]) continue;
        v[a][i] = 1;
        b[a] = i;
        dfs(a+1, n);
        v[a][i] = 0;
    }
}

int main()
{
    n = read(); m = read(); k = read();
    for(int i=1; i<=m; i++)
    {
        p[i].a = read(); p[i].b = read();
    }
    if(n == 1)
    {
        printf("%d\n", k);
        int an = (1+k)*k/2;
        printf("%d\n", an);
        exit(0);
    }
    if(m == 0)
    {
        ll an = 1;
        for(int i=1; i<=n; i++)
        {
            an *= k;
        }
        printf("%lld\n", an);
        dfs(1, n);
        reverse(c+1, c+1+num);
        for(int i=1; i<=num; i++)
        {
            printf("%d", c[i]);
        }
        exit(0);
    }
    
    return 0;
}
View Code

 正解之不加滚动数组也不加高精度所以WA 40

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 503;
const ll mod = 20040820;
const int INF = 2147483647;
const int lim = 1e4 + 1;

int n, m, k, nt[maxn][maxn], g[maxn][maxn];
bool can[520][maxn];
int cnt[maxn][520], sum[maxn][520];
ll an1, an2;

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;
}

inline int lowbit(int x)
{
    return x & -x;
}

int main()
{
    n = read(); m = read(); k = read();
    for(int i=1; i<=m; i++)
    {
        int x = read(), y = read();
        nt[x][y] = 1;
    }
    for(int i=1; i<=k; i++)
    {
        for(int j=1; j<=k; j++)
        {
            if(nt[i][j])
            {
                g[i][++g[i][0]] = j;
            }
        }
    }
    int Max = (1<<k)-1;
    for(int i=0; i<=Max; i++)
    {
        for(int j=1; j<=k; j++)
        {
            can[i][j] = 1;
        }
    }
    for(int j=0; j<=Max; j++)
    {
       int plk = j;
        while(plk)
        {
            int now = lowbit(plk);
            plk -= now;
            int yy = 0;
            while(now>>yy) yy++;
            for(int p=1; p<=g[yy][0]; p++)
            {
                can[j][g[yy][p]] = 0;
            }
        }
    }
    for(int i=0; i<k; i++)
    {
        cnt[1][(1<<i)] = 1;
        sum[1][(1<<i)] = i+1;
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=0; j<=Max; j++)
        {
            for(int p=1; p<=k; p++)
            {
                if(can[j][p])
                {
                    cnt[i+1][j|(1<<(p-1))] += cnt[i][j];
                    sum[i+1][j|(1<<(p-1))] += 10*sum[i][j]+cnt[i][j]*p;
                }
            }
        }
    }
    for(int j=0; j<=Max; j++)
    {
        an1 += cnt[n][j];
        an2 += sum[n][j];
    }
    printf("%lld\n%lld\n", an1, an2);
    
    return 0;
}
WA 40

 然后我加上了高精度和滚动数组TLE 70……

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 503;
const ll mod = 20040820;
const int INF = 2147483647;
const int lim = 1e4 + 1;

int n, m, k, nt[maxn][maxn], g[maxn][maxn];
bool can[520][maxn];
//int cnt[maxn][520], sum[maxn][520];
//ll an1, an2;

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 p[607], len;
    node()
    {
        memset(p, 0, sizeof(p));
        len = 0;
    }
};
node cnt[2][520], sum[2][520], an1, an2;

node operator + (const node &a, const node &b)
{
    node c;
    c.len = max(a.len, b.len);
    int x = 0;
    for(int i=1; i<=c.len; i++)
    {
        c.p[i] = a.p[i] + b.p[i] + x;
        x = c.p[i] / 10;
        c.p[i] %= 10;
    }
    if(x > 0) c.p[++c.len] = x;
    return c;
}

node operator * (const node &a, const int &b)
{
    node c;
    c.len = a.len;
    int x = 0;
    for(int i=1; i<=c.len; i++)
    {
        c.p[i] = a.p[i] * b + x;
        x = c.p[i] / 10;
        c.p[i] %= 10;
    }
    while(x > 0)
    {
        c.p[++c.len] = x % 10;
        x /= 10;
    }
    return c;
}

inline int lowbit(int x)
{
    return x & -x;
}

int main()
{
    n = read(); m = read(); k = read();
    for(int i=1; i<=m; i++)
    {
        int x = read(), y = read();
        nt[x][y] = 1;
    }
    for(int i=1; i<=k; i++)
    {
        for(int j=1; j<=k; j++)
        {
            if(nt[i][j])
            {
                g[i][++g[i][0]] = j;
            }
        }
    }
    int Max = (1<<k)-1;
    for(int i=0; i<=Max; i++)
    {
        for(int j=1; j<=k; j++)
        {
            can[i][j] = 1;
        }
    }
    for(int j=0; j<=Max; j++)
    {
       int plk = j;
        while(plk)
        {
            int now = lowbit(plk);
            plk -= now;
            int yy = 0;
            while(now>>yy) yy++;
            for(int p=1; p<=g[yy][0]; p++)
            {
                can[j][g[yy][p]] = 0;
            }
        }
    }
    int w = 1;
    /*for(int i=0; i<k; i++)
    {
        cnt[w][(1<<i)] = 1;
        sum[w][(1<<i)] = i+1;
    }*/
    for(int i=0; i<k; i++)
    {
        cnt[w][(1<<i)].len = 1; cnt[w][(1<<i)].p[1] = 1;
        sum[w][(1<<i)].len = 1; sum[w][(1<<i)].p[1] = i+1;
    }
    for(int i=1; i<=n; i++)
    {
        w ^= 1;
        for(int j=0; j<=Max; j++)
        {
            cnt[w][j].len = 0; memset(cnt[w][j].p, 0, sizeof(cnt[w][j].p));
            sum[w][j].len = 0; memset(sum[w][j].p, 0, sizeof(sum[w][j].p));
        }
        for(int j=0; j<=Max; j++)
        {
            for(int p=1; p<=k; p++)
            {
                if(can[j][p])
                {
                    cnt[w][j|(1<<(p-1))] = cnt[w^1][j]+cnt[w][j|(1<<(p-1))];
                    sum[w][j|(1<<(p-1))] = sum[w^1][j]*10+cnt[w^1][j]*p+sum[w][j|(1<<(p-1))] ;
                }
            }
        }
    }
    for(int j=0; j<=Max; j++)
    {
        an1 = cnt[w^1][j]+an1;
        an2 = sum[w^1][j]+an2;
    }
    //printf("%lld\n%lld\n", an1, an2);
    for(int i=an1.len; i>0; i--)
    {
        printf("%d", an1.p[i]);
    }
    printf("\n");
    for(int i=an2.len; i>0; i--)
    {
        printf("%d", an2.p[i]);
    }
    
    return 0;
}
View Code

 关于我加了一个m=0的特判它反而变成了TLE 40这件事……难道特判不是这么写的?

if(m == 0)
    {
        node tat, kat;
        int sss = k*(k+1)/2, sf = sss;
        while(sss)
        {
            tat.len++; tat.p[tat.len] = sss%10;
            sss /= 10;
        }
        kat.len = 1; kat.p[1] = k;
        for(int i=1; i<n; i++)
        {
            tat = tat*10*k;
            kat = kat*sf;
            tat = tat + kat;
        }
        for(int i=kat.len; i>0; i--)
        {
            printf("%d", kat.p[i]);
        }
        printf("\n");
        for(int i=tat.len; i>0; i--)
        {
            printf("%d", tat.p[i]);
        }
        exit(0);
    }
if(m==0)

 

 

posted @ 2022-08-03 12:17  Catherine_leah  阅读(28)  评论(1编辑  收藏  举报
/* */