【Henu ACM Round#17 F】Upgrading Array
【链接】 我是链接,点我呀:)
【题意】
在这里输入题意
【题解】
如果我们对某一个位置i操作两次的话。
显然结果就和操作一次一样。
因为第一次操作过后1..i这些数字就变成是互质的了。
gcd为1.那么除过之后没有影响的。
然后。就是要明白
那个f(x)函数的意义。其实就是问你x质因数分解之后,其中好的质数和坏的质数的差是多少。
也即有多少个好因数,多少个坏因数。
(以下的gcd(i)都指的是a[1..i]这些数字的gcd
然后考虑我们在第i个位置进行了一次操作。
显然他会对后面的数字造成影响。
比如在第i个位置进行了一次操作。
那么我们在第i+1个位置进行操作的时候,就会发现gcd(i+1)此时已经不是之前的数字。会变成1.
这样我们可能就会漏解。
因为gcd(i)>=gcd(i+1)
我们可能除得太多了。
使得我们下一次不能除少一点了。
但是如果我们倒过来做的话,就会不一样。
比如我们先在i进行了一次操作。
之后再到i-1进行一次操作的话。
gcd(i-1)不一定就等于1;
因为原先gcd(i-1)>=gcd(i)
所以在i进行的操作的时候。
我们下一次到某个小于i的位置的时候,
只需记录一下上一次已经除掉了多少。
这次再加的时候去掉上次的影响就好了。
但是假设我们在i,j,k(i<j<k)这3个位置都进行了操作。
我们只需要记录gcd(j)就好。
因为gcd(k)肯定包含在gcd(j)中了。
然后在j位置的影响再累加一下就是gcd(k)了;
然后在i位置的影响就是gcd(i)/gcd(k)了;
也就是说,我们在算gcd(i)的好素数和坏素数差的时候,只需要把它当成gcd(i)/gcd(k)算就好了。
(前提是之前已经选过k这个位置了。
根据上面的分析我们可以用动态规划来解决这个问题了。
需要维护两个量,1个是当前的位置,另外就是上一次进行操作的位置。
每个位置i有两种选择:
1.不进行操作,则上一次进行操作的位置不变。
2.进行一次操作,则上一次进行操作的位置变成i.
设f(x)表示x的美丽值。
dp[i][j]表示前i个位置,上一次选择的位置是j的最大美丽值。
则
\(dp[i][i] = max(dp[i][i],dp[i+1][j]+(gcd[j]-gcd[i])*i; 第i个位置进行一次操作\)
\(dp[i][j] = max(dp[i][j],dp[i+1][j]);第i个位置不进行一次操作\)
初值dp[n+1][n+1]等于\(∑f(a[i])\)
(即不进行任何操作
(这里n+1就表示之前没有进行任何一次操作的情况。
(根据上面的讨论,不难想到这个dp应该倒序做即i倒序。但是j的话随意吧。
最后取max(dp[i][j])就是答案了。
【代码】
#include <bits/stdc++.h>#define ll long longusing namespace std;const int N = 5e3;int n, m, a[N + 10],_gcd[N+10];int dp[N + 10][N + 10];//前i个数字,上一次操作的位置在j的最大美丽值。set<int> myset;map<int, int> dic;int gcd(int x, int y) {if (y == 0)return x;elsereturn gcd(y, x%y);}int f(int x) {if (x <= 1) return dic[x] = 0;if (dic.find(x) != dic.end()) return dic[x];int temp = x,point = 0;for (int i = 2; i*i <= temp; i++)if (temp%i == 0) {int flag = 0;if (myset.find(i) != myset.end()) {//找到了flag = -1;}else {flag = 1;}while (temp%i == 0) {temp /= i;point += flag;}}if (temp > 1) {if (myset.find(temp) != myset.end())point--;elsepoint++;}return dic[x] = point;}int main() {#ifdef LOCAL_DEFINEfreopen("rush_in.txt", "r", stdin);#endifios::sync_with_stdio(0), cin.tie(0);cin >> n >> m;for (int i = 1; i <= n; i++) cin >> a[i];_gcd[1] = a[1];for (int i=2; i <= n; i++) _gcd[i] = gcd(_gcd[i - 1], a[i]);for (int i = 1; i <= m; i++) {int x;cin >> x;myset.insert(x);}memset(dp, -0x3f3f3f3f, sizeof dp);dp[n + 1][n + 1] = 0;for (int i = 1; i <= n; i++) dp[n+1][n + 1] += f(a[i]);for (int i = n;i >= 1;i--)for (int j = n + 1; j > i; j--) {//在i这个位置放一个dp[i][i] = max(dp[i][i], dp[i + 1][j] +f(_gcd[j])*i- f(_gcd[i]) * i);//i这个位置不放dp[i][j] = max(dp[i][j], dp[i + 1][j]);}int ans = dp[n + 1][n + 1];for (int i = 1; i <= n; i++)for (int j = i; j <= n; j++)ans = max(ans, dp[i][j]);cout << ans << endl;return 0;}
【Henu ACM Round#17 F】Upgrading Array的更多相关文章
- 【Henu ACM Round#16 F】Om Nom and Necklace
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] KMP算法可以把"i前缀"pre[i] 分成ssssst的形式 这里t是s的前缀. 然后s其实就是pre[i]中 ...
- 【Henu ACM Round#17 E】Tree Construction
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 做这题之前先要知道二叉排序树的一个性质. 就是它的中序遍历的结果就是这个数组升序排序. (且每个节点的左边的节点都是比这个节点的值小 ...
- 【Henu ACM Round#17 C】Kitahara Haruki's Gift
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 判断sum/2这个价值能不能得到就可以了. 则就是一个01背包模型了. 判断某个价值能否得到. f[j]表示价值j能否得到. f[0 ...
- 【Henu ACM Round#17 B】USB Flash Drives
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 排序,逆序.贪心选较大的就好. [代码] #include <bits/stdc++.h> #define ll lon ...
- 【Henu ACM Round #13 F】Fibonacci-ish
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举序列的头两个数字是什么 O(N^2) 然后头两个数字确定之后. f[3],f[4]..就确定了 只需查看f[3],f[4]..是 ...
- 【Henu ACM Round#15 F】Arthur and Questions
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] a1+a2+...+ak<a2+a3+...ak+1 ->a1<ak+1 a2+a3+...+ak+1<a3 ...
- 【Henu ACM Round#18 F】Arthur and Walls
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 考虑,为什么一个连通块里面的空格没有变成一个矩形? 如果不是形成矩形的话. 肯定是因为某个2x2的单张方形里面. 只有一个角是墙.其 ...
- 【Henu ACM Round#20 F】 Arthur and Brackets
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 所给的li,ri是左括号从左到右的顺序给的. (且注意长度是2*n 现在我们先把第一个左括号放在第1个位置. 然后考虑第二个位置. ...
- 【Henu ACM Round#19 F】Dispute
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 这一题和这一题很像 (链接 ) 会发现如果a[i]!=b[i]那么就按下i就好了. 然后改变和他相邻的点. 此后a[i]再也不可能和 ...
随机推荐
- Ubuntu系统下安装Eclipse
第一步:查看操作系统位数. 打开终端,输入file /sbin/init 可以看到笔者Ubuntu系统为32位,读者可以使用该命令获取自己机器上的操作系统位数. 这一步是最至关重要的一步,笔者机器处理 ...
- POJ 3320 Jessica's Reading Problem (尺取法,时间复杂度O(n logn))
题目: 解法:定义左索引和右索引 1.先让右索引往右移,直到得到所有知识点为止: 2.然后让左索引向右移,直到刚刚能够得到所有知识点: 3.用右索引减去左索引更新答案,因为这是满足要求的子串. 4.不 ...
- 1028C:Rectangles
You are given n rectangles on a plane with coordinates of their bottom left and upper right points. ...
- java中的json使用
import org.json.simple.JSONArray;import org.json.simple.JSONObject; /** * 使用的是json-lib-2.4.jar * @au ...
- jQuery更改样式
$(".input_check_2").css("left","31px"); //更改left的值
- 浅谈htmlentities 、htmlspecialchars、addslashes的使用方法
html_entity_decode():把html实体转换为字符. $str = "just atest & 'learn to use '"; echo html_en ...
- org.apache.ibatis.binding.BindingException: Parameter ‘brOrderNo’ not found. Available parameters ar
最近使用 mybatis 写项目的时候遇到报错:org.apache.ibatis.binding.BindingException: Parameter 'brOrderNo' not found. ...
- 2017年6月28日 python爬虫学习
1.写入csv文件2.lxml的用法3.自定义字典类的方法4.bytes解码得到str,str编码得到bytes5.json 1 import csv import lxml.html class S ...
- 《Craking the Coding interview》python实现---02
###题目:翻转一个字符串###思路:从字符串的最后一位开始,依次取###实现:伪代码.函数.类实现#伪代码: #01string=sNew_s=""for i in range( ...
- 表达式中含or的赋值
or用在赋值表达式的时候,不是返回bool值,而是按以下的情况赋值 如果左侧的表达式估值为True,则返回左侧表达式 否则返回右侧表达式 例子: insignificance = 3 or 1 pri ...