Codeforces 990 调和级数路灯贪心暴力 DFS生成树两子树差调水 GCD树连通块暴力

A

水题

/*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
const int mod = 1e9 + 7, gakki = 5 + 2 + 1 + 19880611 + 1e9;
const int MAXN = 1e5 + 5, MAXM = 1e5 + 5, N = 1e5 + 5;
const int MAXQ = 100010;
int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1;
inline void addedge(int u, int v)
{
        to[++tot] = v;
        nxt[tot] = Head[u];
        Head[u] = tot;
}
int main()
{
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        ll n, m, a, b;
        cin >> n >> m >> a >> b;
        if (n % m == 0)
        {
                cout << 0 << endl;
                return 0;
        }
        ll now = n / m;
        ll ans1 = (n - now * m) * b;
        ll ans2 = ((now + 1) * m - n) * a;
        cout << min(ans1, ans2) << endl;
        return 0;
}
View Code

B

题目说了 在某个数之前K范围内的都能被消除掉 所以直接作一个前缀和即可

/*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
const int mod = 1e9 + 7, gakki = 5 + 2 + 1 + 19880611 + 1e9;
const int MAXN = 1e5 + 5, MAXM = 1e5 + 5, N = 2e5 + 5;
const int MAXQ = 100010;
int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1;
inline void addedge(int u, int v)
{
        to[++tot] = v;
        nxt[tot] = Head[u];
        Head[u] = tot;
}
int num[N];
int visit[2000005];
priority_queue<int, vector<int>, greater<int> >que;
int main()
{
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        int n, k;
        cin >> n >> k;
        int anser = 0;
        for (int i = 1; i <= n; i++)
        {
                cin >> num[i];
                int l = max(num[i] - k, 0);
                visit[l]++;
                visit[num[i]]--;
        }
        for (int i = 1; i <= 2000000; i++)
        {
                visit[i] += visit[i - 1];
        }
        for (int i = 1; i <= n; i++)
        {
                if (!visit[num[i]])
                {
                        anser++;
                }
        }
        cout << anser << endl;
        return 0;
}
View Code

C

卡题意题..最后弱智答案没遍历完全FST了QAQ

/*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
const int mod = 1e9 + 7, gakki = 5 + 2 + 1 + 19880611 + 1e9;
const int MAXN = 1e5 + 5, MAXM = 1e5 + 5, N = 2e5 + 5;
const int MAXQ = 100010;
int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1;
inline void addedge(int u, int v)
{
        to[++tot] = v;
        nxt[tot] = Head[u];
        Head[u] = tot;
}
ll n, flag, cnt, pop;
ll anser = 0;
string ch[300005];
ll number[300005];
ll ansl[300005];
ll ansr[300005];
void init()
{
        pop = 0, cnt = 0, flag = 0;
}
int main()
{
        int n;
        cin >> n;
        for (int i = 1; i <= n; i++)
        {
                init();
                cin >> ch[i];
                for (int j = 0; j < ch[i].size(); j++)
                {
                        if (ch[i][j] == '(')
                        {
                                number[++pop] = 1;
                        }
                        else
                        {
                                number[++pop] = -1;
                        }
                }
                for (int i = 1; i <= pop; i++)
                {
                        cnt += number[i];
                        if (cnt < 0)
                        {
                                flag = 1;
                                break;
                        }
                }
                if (!flag)
                {
                        ansl[cnt]++;
                }
                flag = cnt = 0;
                for (int i = pop; i >= 1; i--)
                {
                        cnt -= number[i];
                        if (cnt < 0)
                        {
                                flag = 1;
                                break;
                        }
                }
                if (!flag)
                {
                        ansr[cnt]++;
                }
        }
        for (int i = 0; i <= 300000; i++)
        {
                anser += ansl[i] * ansr[i];
        }
        cout << anser << endl;
}
View Code

D

构造题

/*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
const int mod = 1e9 + 7, gakki = 5 + 2 + 1 + 19880611 + 1e9;
const int MAXN = 1e5 + 5, MAXM = 1e5 + 5, N = 2e5 + 5;
const int MAXQ = 100010;
int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1;
inline void addedge(int u, int v)
{
        to[++tot] = v;
        nxt[tot] = Head[u];
        Head[u] = tot;
}
int ans[1005][1005];
int main()
{
        int n;
        int a, b;
        cin >> n >> a >> b;
        if (min(a, b) != 1)
        {
                cout << "NO" << endl;
                return 0;
        }
        if ((n == 2 && a == 1 && b == 1) || (n == 3 && a == 1 && b == 1))
        {
                cout << "NO" << endl;
                return 0;
        }
        if (a > 1 && b == 1)
        {
                for (int i = 1; i <= n; i++)
                {
                        for (int j = 1; j <= n; j++)
                        {
                                if (i != j)
                                {
                                        ans[i][j] = 1;
                                }
                        }
                }
                for (int i = 1; i <= a - 1; i++)
                {
                        for (int j = 1; j <= n; j++)
                        {
                                ans[i][j] = 0;
                                ans[j][i] = 0;
                        }
                }
                cout << "YES" << endl;
                for (int i = 1; i <= n; i++)
                {
                        for (int j = 1; j <= n; j++)
                        {
                                cout << ans[i][j];
                        }
                        cout << endl;
                }
                return 0;
        }
        if (a == 1 && b == 1)
        {
                for (int i = 1; i <= n; i++)
                {
                        ans[i][i + 1] = ans[i + 1][i] = 1;
                }
                cout << "YES" << endl;
                for (int i = 1; i <= n; i++)
                {
                        for (int j = 1; j <= n; j++)
                        {
                                cout << ans[i][j];
                        }
                        cout << endl;
                }
                return 0;
        }
        if (a == 1 && b > 1)
        {
                for (int i = 1; i <= b - 1; i++)
                {
                        for (int j = 1; j <= n; j++)
                        {
                                if (i != j)
                                {
                                        ans[i][j] = ans[j][i] = 1;
                                }
                        }
                }
                cout << "YES" << endl;
                for (int i = 1; i <= n; i++)
                {
                        for (int j = 1; j <= n; j++)
                        {
                                cout << ans[i][j];
                        }
                        cout << endl;
                }
                return 0;
        }
}
View Code

E

直接把灯尽量往右放 贪心暴力即可 复杂度和调和级数有关 并不会炸

有些人暴力的姿势不对会FST

/*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
const int mod = 1e9 + 7, gakki = 5 + 2 + 1 + 19880611 + 1e9;
const int MAXN = 1e5 + 5, MAXM = 1e5 + 5, N = 2e6 + 5;
const int MAXQ = 100010;
int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1;
inline void addedge(int u, int v)
{
        to[++tot] = v;
        nxt[tot] = Head[u];
        Head[u] = tot;
}
int n, m, k;
int visit[2000005], has_block[2000006], lighttt[2000005];
ll anser;
int pop, summm, a1, a2;
void init()
{
        summm = pop = 1;
}
int main()
{
        ios_base::sync_with_stdio(0);
        cin.tie(0);
        anser = LLONG_MAX;
        int n, m, k, now;
        cin >> n >> m >> k;
        n++;
        for (int i = 1; i <= m; i++)
        {
                cin >> now;
                visit[now + 1] = 1;
        }
        if (visit[1])
        {
                cout << -1 << endl;
                return 0;
        }
        for (int i = 1; i <= k; i++)
        {
                cin >> lighttt[i];
        }
        for (int i = 1; i <= n; i++)
        {
                if (visit[i])
                {
                        has_block[i] = has_block[i - 1];
                }
                else
                {
                        has_block[i] = i;
                }
        }
        for (int i = 1; i <= k; i++)
        {
                init();
                while (1)
                {
                        if (pop + i >= n)
                        {
                                ll cnt = 1LL*summm * lighttt[i];
                                anser = min(anser, cnt);
                                break;
                        }
                        if (pop == has_block[pop + i])
                        {
                                break;
                        }
                        summm++;
                        pop = has_block[pop + i];
                }
        }
        if (anser == LLONG_MAX)
        {
                cout << -1 << endl;
        }
        else
        {
                cout << anser << endl;
        }
}
View Code

F

首先很显然 因为传递不改变总值而要求是每个点的值都为0 所以当点的总值不为0时 是Impossible

然后我们要做的就是 DFS出一个生成树 然后从叶子到根传递出以一个顶点为根的子树其值的总值

因为每条边连接有两个顶点 这条边可以把这颗树分为两个子树 但题目要求是全部节点的值为0

所以最终要求是这两个子树的值也为0 则这条边传递的值 一定是 |其中一个子树的总值-0|  再判一下方向即可

其他没用到的边 答案是0 直接输出就行了

/*Huyyt*/
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
const int mod = 1e9 + 7, gakki = 5 + 2 + 1 + 19880611 + 1e9;
const int MAXN = 2e5 + 5, MAXM = 2e5 + 5, N = 2e5 + 5;
const int MAXQ = 100010;
int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1;
inline void addedge(int u, int v)
{
        to[++tot] = v;
        nxt[tot] = Head[u];
        Head[u] = tot;
}
inline void read(int &v)
{
        v = 0;
        char c = 0;
        int p = 1;
        while (c < '0' || c > '9')
        {
                if (c == '-')
                {
                        p = -1;
                }
                c = getchar();
        }
        while (c >= '0' && c <= '9')
        {
                v = (v << 3) + (v << 1) + c - '0';
                c = getchar();
        }
        v *= p;
}
int value[MAXN], visit[MAXN], ans[MAXM << 1];
int dfs(int x)
{
        int now = value[x];
        visit[x] = 1;
        for (int i = Head[x]; i; i = nxt[i])
        {
                int v = to[i];
                if (!visit[v])
                {
                        int nownxt = dfs(v);
                        now += nownxt;
                        if (i & 1)
                        {
                                ans[i ^ 1] = -nownxt;
                        }
                        else
                        {
                                ans[i] = nownxt;
                        }
                }
        }
        return now;
}
int main()
{
        ios_base::sync_with_stdio(0);
        cin.tie(0);

        int sum = 0;
        int n, m, u, v;
        read(n);
        for (int i = 1; i <= n; i++)
        {
                read(value[i]);
                sum += value[i];
        }
        read(m);
        for (int i = 1; i <= m; i++)
        {
                read(u), read(v);
                addedge(u, v), addedge(v, u);
        }
        if (sum != 0)
        {
                printf("Impossible\n");
                return 0;
        }
        printf("Possible\n");
        dfs(1);
        for (int i = 1; i <= m; i++)
        {
                printf("%d\n", ans[i << 1]);
        }
        return 0;
}
View Code

 G

也是个暴力题..把GCD搞出来 然后看连通块就行了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 222222
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
struct Line{int v,next;}e[MAX<<1];
int h[MAX],cnt=1,mx;
inline void Add(int u,int v){e[cnt]=(Line){v,h[u]};h[u]=cnt++;}
vector<int> ys[MAX];
int n,a[MAX],tot;
bool book[MAX],vis[MAX];
ll ans[MAX];
void Div(int x,int id)
{
    for(int i=1,m=sqrt(x);i<=m;++i)
        if(x%i==0)
        {
            ys[i].push_back(id);
            if(i*i!=x)ys[x/i].push_back(id);
        }
}
void dfs(int u,int ff)
{
    if(!book[u])return;
    vis[u]=true;++tot;
    for(int i=h[u];i;i=e[i].next)
        if(e[i].v!=ff)dfs(e[i].v,u);
}
int main()
{
    n=read();
    for(int i=1;i<=n;++i)mx=max(mx,a[i]=read());
    for(int i=1;i<=n;++i)Div(a[i],i);
    for(int i=1;i<n;++i)
    {
        int u=read(),v=read();
        Add(u,v);Add(v,u);
    }
    for(int i=1;i<=mx;++i)
    {
        for(int j=0,l=ys[i].size();j<l;++j)
        {
            int v=ys[i][j];
            vis[v]=false;book[v]=true;
        }
        for(int j=0,l=ys[i].size();j<l;++j)
        {
            tot=0;int v=ys[i][j];
            if(!vis[v])dfs(v,0);book[v]=false;
            ans[i]+=1ll*tot*(tot-1)/2+tot;
        }
    }
    for(int i=mx;i;--i)
        if(ans[i])for(int j=i+i;j<=mx;j+=i)ans[i]-=ans[j];
    for(int i=1;i<=mx;++i)
        if(ans[i])printf("%d %I64d\n",i,ans[i]);
    return 0;
}
View Code

 

posted @ 2018-06-10 22:08  Aragaki  阅读(365)  评论(0编辑  收藏  举报