zoukankan      html  css  js  c++  java
  • dfs模拟暴力(ecfinal M题)

    https://codeforces.com/gym/102471/problem/M

    题意:给你集合A of {1,2,,n} , 求子集的最大分数

    给出a[1],a[2]...a[n] 和 b[1],b[2]...b[n].

    积分规则:

    1、初始分数为0.

    2、每一个加入集合的i加上a【i】分数

    3、集合中任意 (i,j) 满足i≥2, j≥2, i∈A and j∈A, 有 k>1 i的k次方=j, 就减掉b【j】分数。

    解法:sqrt(n)个数每个数存在次方关系的下标单拎出来,进行dfs暴力选与不选.

    #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
    #define gcd __gcd
    const int inf = 0x3f3f3f3f;
    const int maxn = 100100;
    const int M = 1e9+7;
    int n,k;
    ll a[maxn],b[maxn];
    bool vis[maxn];
    
    ll val[maxn],sub[maxn];
    bool slt[maxn];         //select
    ll mx;
    
    void dfs(int idx,ll sum)
    {
        if(idx == k)
        {
            mx = max(mx,sum);
            return;
        }
        slt[idx] = 1;      //选
        ll temp = sum+val[idx];
        for(int i = 1; i < idx; i++)
        {
            if(slt[i] && idx%i == 0) temp -= sub[idx];
        }
        dfs(idx+1,temp);
        slt[idx] = 0;       //回溯,不选
        dfs(idx+1,sum);
    }
    
    ll solve(int x)
    {
        k = 1;
        for(int i = x; i <= n; i*=x)
        {
            vis[i] = 1;
            val[k] = a[i];
            sub[k] = b[i];
            k++;
        }
        mx = 0;
        //memset(slt , false , sizeof(slt));
        dfs(0,0);
        return mx;
    }
    
    int main()
    {
    /*#ifdef ONLINE_JUDGE
    #else
        freopen("data.in", "r", stdin);
        //freopen("data.out", "w", stdout);
    #endif*/
        scanf("%d",&n);
        for(int i = 1; i <= n; i++)
        {
            scanf("%lld",&a[i]);
        }
        for(int i = 1; i <= n; i++)
        {
            scanf("%lld",&b[i]);
        }
        ll ans = 0;
        for(int i = 2; i <= sqrt(n); i++)
        {
            if(!vis[i])ans += solve(i);//注意不要重复领出来,领一次就可以
        }
        for(int i = 1; i <= n; i++)
        {
            if(!vis[i]) ans += a[i];
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Linux脚本文件注释
    Linux三剑客之grep命令
    Linux获取本机IP
    Linux的cut命令详解
    Linux的wc命令详解
    Linux的uniq命令详解
    Linux的sort命令详解
    shell之a+b求和脚本的三种写法
    shell的文件比较运算符和字符串比较运算符
    shell中变量$系列的含义
  • 原文地址:https://www.cnblogs.com/nonames/p/12156268.html
Copyright © 2011-2022 走看看