Codeforces 922 思维贪心 变种背包DP 质因数质数结论

A

#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!
")
#define pb push_back
#define inf 1e9
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-8;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 3e7 + 10;
const int  maxm = 300;
const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
ll mod = 1e9 + 7;
int main()
{
        int x, y;
        cin >> x >> y;
        if (x == 0 || y == 0)
        {
                if (x == 0 && y == 1)
                {
                        cout << "Yes" << endl;
                }
                else
                {
                        cout << "No" << endl;
                }
                return 0;
        }
        int cur = y - 1;
        int remain = x - cur;
        if (remain % 2 == 0 && cur && remain>=0)
        {
                cout << "Yes" << endl;
                return 0;
        }
        cout << "No" << endl;
        return 0;
}
View Code

B

#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!
")
#define pb push_back
#define inf 1e9
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-10;
const double EPS = 1.0e-4;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
//const int maxn = 3e5 + 10;
const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
ll Mod = 1000000007;
int num[10000];
int cnt;
bool check(int a, int b, int c)
{
        if (a + b > c && a + c > b && b + c > a)
        {
                return true;
        }
        return false;
}
int main()
{
        int n;
        int anser = 0;
        cin >> n;
        for (int i = 1; i < n; i++)
        {
                for (int j = i + 1; j <= n; j++)
                {
                        int aim = (i ^ j);
                        if (aim >= j && aim <= n && check(i, j, aim))
                        {
                                //cout << i << " " << j << " " << aim << endl;
                                anser++;
                        }
                }
        }
        cout << anser << endl;
        return 0;
}
View Code

C

#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!
")
#define pb push_back
#define inf 1e9
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-10;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
//const int maxn = 3e5 + 10;
const int  maxn = 100005;
const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
const int turn2[8][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}, {1, -1}, { -1, -1}, {1, 1}, { -1, 1}};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
int main()
{
        //freopen("sample.txt", "w", stdout);
        ll n, k;
        cin >> n >> k;
        if (n == 1 && k <= 2)
        {
                cout << "Yes" << endl;
                return 0;
        }
        if (k >= n)
        {
                cout << "No" << endl;
        }
        else
        {
                for (ll i = 1; i <= min(1LL * 50, k); i++)
                {
                        if (n % i != i - 1)
                        {
                                cout << "No" << endl;
                                return 0;
                        }
                }
                cout << "Yes" << endl;
        }
        return 0;
}
View Code

D

奇葩贪心题 假设有两个字符串A B A在B前面的条件是什么?

假设A有SHa个sh BSHb A有Sa个s BSb A有Ha个h BHb 当 SHa+SHb+Sa*Hb>SHa+SHb+Sb*Ha 时成立

转换一下就是A的sh比例比B高的时候 A在B前面

#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!
")
#define pb push_back
#define inf 1e9
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-10;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
//const int maxn = 3e5 + 10;
const int  maxn = 100005;
const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
const int turn2[8][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}, {1, -1}, { -1, -1}, {1, 1}, { -1, 1}};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
struct node
{
        string str;
        double per;
} s[100005];
bool operator <(node a, node b)
{
        return a.per > b.per;
}
ll pre[100005];
string aim = "";
int main()
{
        ll anser = 0;
        //freopen("sample.txt", "w", stdout);
        int n;
        cin >> n;
        for (int i = 1; i <= n; i++)
        {
                int now = 0;
                cin >> s[i].str;
                int len = s[i].str.size();
                for (int j = 0; j < len; j++)
                {
                        if (s[i].str[j] == 's')
                        {
                                now++;
                        }
                }
                if (len - now == 0)
                {
                        s[i].per = 1000000;
                }
                else
                {
                        s[i].per = (double)now / (double)(len - now);
                }
                //cout << s[i].per << endl;
        }
        sort(s + 1, s + 1 + n);
        for (int i = 1; i <= n; i++)
        {
                aim += s[i].str;
        }
        //cout << aim << endl;
        int lenth = aim.size();
        for (int i = 0; i < lenth; i++)
        {
                if (i == 0)
                {
                        pre[i] = (aim[i] == 's');
                }
                else
                {
                        pre[i] = pre[i - 1] + (aim[i] == 's');
                }
                if (aim[i] == 'h')
                {
                        anser += pre[i];
                }
        }
        cout << anser << endl;
        return 0;
}
View Code

E

一般想到的DP思路是DP[i][j]表示前i个用了j块钱能吸引多少鸟 但是这里j太大了(于是题目就提示你C[i]的总值不超过10000)

所以用DP[i][j]表示在前i个吸引了j个鸟最多好剩多少魔力   复杂度:Codeforces 922 思维贪心 变种背包DP 质因数质数结论   前面的复杂度是pre[i]较小的时候 后面是pre[i]较大的时候

DP方程:Codeforces 922 思维贪心 变种背包DP 质因数质数结论

#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!
")
#define pb push_back
#define inf 1e9
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-10;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
//const int maxn = 3e5 + 10;
const int  maxn = 100005;
const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
const int turn2[8][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}, {1, -1}, { -1, -1}, {1, 1}, { -1, 1}};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
ll n, W, B, X;
ll c[1005];
ll pre[1005];
ll cost[1005];
ll dp[1005][10005];
int main()
{
        //freopen("sample.txt", "w", stdout);
        // W初始值 B增加的上限 X回复的数目
        mem(dp, -1);
        cin >> n >> W >> B >> X;
        dp[0][0] = W;
        for (int i = 1; i <= n; i++)
        {
                cin >> c[i];
                pre[i] = pre[i - 1] + c[i];
        }
        for (int i = 1; i <= n; i++)
        {
                cin >> cost[i];
        }
        for (ll i = 1; i <= n; i++)
        {
                for (ll j = 0; j <= pre[i]; j++)
                {
                        for (ll k = 0; k <= min(j, c[i]); k++)
                        {
                                if (dp[i - 1][j - k] == -1 || 1LL * cost[i]*k > dp[i - 1][j - k])
                                {
                                        continue;
                                }
                                dp[i][j] = max(dp[i][j], dp[i - 1][j - k] - 1LL * k * cost[i]);
                        }
                        if (dp[i][j] != -1)
                        {
                                dp[i][j] = min(dp[i][j] + X, W + 1LL * j * B);
                        }
                }
        }
        for (int i = pre[n]; i >= 0; i--)
        {
                if (dp[n][i] >= 0)
                {
                        cout << i << endl;
                        return 0;
                }
        }
        return 0;
}
View Code

 F

先N*lnN处理出每个数的被除数个数 然后做前缀和 如果K>dp[N] 就无解

所以猜测 当dp[i]>=k时即有解 当数据大于10时 dp数列每两个之间相差不会超过各自之下的i/2+1~i的质数个数(为什么选i/2~i的质数是因为其sum[i]只为1 方便调整)

所以当N>10的时候找到最小的满足dp[i]>=k的i 然后用删去其i/2+1~i之间的质数来调整 dp[i]-k

后来知道 当N<=10的时候 也满足>10的解法  一个数N的被整除数在N^(1/3)数量级 质数则在 N/LogN数量级

#include <bits/stdc++.h>
#define PI acos(-1.0)
#define mem(a,b) memset((a),b,sizeof(a))
#define TS printf("!!!
")
#define pb push_back
#define inf 1e9
//std::ios::sync_with_stdio(false);
using namespace std;
//priority_queue<int,vector<int>,greater<int>> que; get min
const double eps = 1.0e-10;
const double EPS = 1.0e-4;
typedef pair<int, int> pairint;
typedef long long ll;
typedef unsigned long long ull;
//const int maxn = 3e5 + 10;
const int turn[4][2] = {{1, 0}, { -1, 0}, {0, 1}, {0, -1}};
//priority_queue<int, vector<int>, less<int>> que;
//next_permutation
ll Mod = 1000000007;
vector<int> prime;
int n;
ll k;
int anserten;
ll sum[300005];
ll dp[300005];
int visit[300005];
void dfs(int pos, int x)
{
        if (pos == n + 1)
        {
                if (anserten == 0)
                {
                        int now = 0;
                        for (int i = 1; i <= 5; i++)
                        {
                                if (x & (1 << i))
                                {
                                        for (int j = i * 2; j <= 10; j += i)
                                        {
                                                if (x & (1 << j))
                                                {
                                                        //cout << i << " " << j << endl;
                                                        now++;
                                                }
                                        }
                                }
                        }
                        if (now == k)
                        {
                                anserten = x;
                        }
                }
                return ;
        }
        dfs(pos + 1, x + (1 << pos));
        dfs(pos + 1, x);
}
priority_queue<pair<int, int> > que;
int main()
{
        cin >> n >> k;
        for (int i = 1; i <= n; i++)
        {
                for (int j = i * 2; j <= n; j += i)
                {
                        sum[j]++;
                }
        }
        for (int i = 1; i <= n; i++)
        {
                dp[i] = dp[i - 1] + sum[i];
        }
        if (k > dp[n])
        {
                cout << "No" << endl;
                return 0;
        }
        else
        {
                cout << "Yes" << endl;
                if (n <= 10)
                {
                        dfs(1, 0);
                        int anser = 0;
                        for (int i = 1; i <= 10; i++)
                        {
                                if (anserten & (1 << i))
                                {
                                        anser++;
                                }
                        }
                        cout << anser << endl;
                        for (int i = 1; i <= 10; i++)
                        {
                                if (anserten & (1 << i))
                                {
                                        cout << i << " ";
                                }
                        }
                        cout << endl;
                }
                else
                {
                        dp[n + 1] = INT_MAX;
                        int aim;
                        for (aim = 1; aim <= n; aim++)
                        {
                                if (dp[aim] >= k && dp[aim - 1] < k)
                                {
                                        break;
                                }
                        }
                        int anser = aim;
                        for (int i = aim; i >= 1; i--)
                        {
                                visit[i] = 1;
                        }
                        for (int i = aim; i >= aim / 2 + 1; i--)
                        {
                                que.push({sum[i], i});
                        }
                        int cha = dp[aim] - k;
                        pair<int, int> cnt;
                        while (cha > 0)
                        {
                                cnt = que.top();
                                que.pop();
                                if (cnt.first <= cha)
                                {
                                        cha -= cnt.first;
                                        visit[cnt.second] = 0;
                                        anser--;
                                }
                        }
                        cout << anser << endl;
                        for (int i = 1; i <= aim; i++)
                                if (visit[i])
                                {
                                        cout << i << " ";
                                }
                        cout << endl;
                }
        }
        return 0;
}
View Code

相关推荐