CodeForces 402D Upgrading Array
2015-08-21 15:36
141 查看
http://codeforces.com/problemset/problem/402/D
题意:
给了一串序列,计算出这个序列最小的∑\sumf(a[i])f(a[i])。定义了f(s)f(s),给了个公式。可以进行一系列的操作,这个操作为从1~r 这些数都除以他们的gcd。让你最后算出最后最小∑\sumf(a[i])f(a[i])是多少。当然如果不需要进行操作就可以达到最小,也是可以的。
思路:
首先要看出所定义的f(s)f(s)的那个公式其实就是代表的是将s分解为质因数的乘积之后,好的素数有几个,坏的素数为几个,好的+1,坏的-1.
那么如果要使最后序列的总和最小说明要让每个元素的好的素数尽可能的大,坏的素数尽可能的小。
因为可以进行除以gcd的操作,可以先求出1~r的gcd记录下来。因为前面的gcd肯定是不小于后面的gcd的,所以要从后往前判断是否要进行这个操作,不然前面进行这个操作之后后面有可能不能进行。
对于每个当前位置要判断是否要进行这个操作。要让这些数的好素数多,坏素数少,那么就可以判断当前要除掉的这个gcd可以分解成几个好素数几个坏素数,如果坏的多于好的,就将前面的数都除掉这个gcd(除掉的同时记得前面的gcd也要除掉这个gcd),这样就减少了坏的个数。少于就不除,相等话都可以,不影响结果。。
题意:
给了一串序列,计算出这个序列最小的∑\sumf(a[i])f(a[i])。定义了f(s)f(s),给了个公式。可以进行一系列的操作,这个操作为从1~r 这些数都除以他们的gcd。让你最后算出最后最小∑\sumf(a[i])f(a[i])是多少。当然如果不需要进行操作就可以达到最小,也是可以的。
思路:
首先要看出所定义的f(s)f(s)的那个公式其实就是代表的是将s分解为质因数的乘积之后,好的素数有几个,坏的素数为几个,好的+1,坏的-1.
那么如果要使最后序列的总和最小说明要让每个元素的好的素数尽可能的大,坏的素数尽可能的小。
因为可以进行除以gcd的操作,可以先求出1~r的gcd记录下来。因为前面的gcd肯定是不小于后面的gcd的,所以要从后往前判断是否要进行这个操作,不然前面进行这个操作之后后面有可能不能进行。
对于每个当前位置要判断是否要进行这个操作。要让这些数的好素数多,坏素数少,那么就可以判断当前要除掉的这个gcd可以分解成几个好素数几个坏素数,如果坏的多于好的,就将前面的数都除掉这个gcd(除掉的同时记得前面的gcd也要除掉这个gcd),这样就减少了坏的个数。少于就不除,相等话都可以,不影响结果。。
[code]#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> using namespace std; #define M 50009 #define N 1000000009 int dp[M]; int a[M]; int n,m; map<int,int> bad; int gcd(int a,int b) { if(b == 0) return a; return gcd(b,a%b) ; } int cal(int a) //分解质因数。 { int sum = 0; for(int i = 2;i*i <= a;i++) { while(a % i == 0) { if(bad[i]) sum--; else sum++; a /= i; } } if(a != 1) //不要漏了最后还是素数的情况,调了十年。。 { if(bad[a]) sum--; else sum++; } return sum; } int main() { while(scanf("%d %d",&n,&m)==2) { bad.clear(); for(int i = 0;i < n;i++) { scanf("%d",&a[i]); } dp[0] = a[0]; dp[1] = gcd(a[0],a[1]); for(int i = 2;i < n;i++) { dp[i] = gcd(dp[i-1],a[i]); } for(int i = 0;i < m;i++) { int temp; scanf("%d",&temp); bad[temp]++; } for(int i = n-1;i >= 0;i--) { int p = dp[i]; int temp = cal(dp[i]); if(temp < 0) { for(int j = i;j >= 0;j--) { a[j] /= p; dp[j] /= p; } } } int sum = 0; for(int i = 0;i < n;i++) { sum += cal(a[i]); } printf("%d\n",sum); } return 0; }
相关文章推荐
- Apache与IIS的客观对比(不比不知道,一比吓一跳)
- 模板 - 最长公共子序列
- 黑马程序员-[C语言-指针和文件操作]学习日记(四)
- POJ1088滑雪(记忆化搜索+DFS||经典的动态规划)
- appium安装
- oralce11g agent与oms无法连接
- TCP/IP-链路层
- 输出货币值
- jmc监控工具
- Linux 错误:fatal error: uuid/uuid.h: No such file or directory
- Android应用程序组件(二)
- Invert Binary Tree(翻转二叉树)
- 在C#中调用格式工厂进行任意视频格式到FLV的转换
- Execution failed for task ':app:compileDebugNdk'
- [2016实习] 摩根大通-量化金融-北京
- jquery实现叠层3D文字特效代码分享
- 通过rsync远程增量备份(差异备份)
- mysql--------InnoDB和MyISAM的区别
- 关于android:id="@+id/xx"的理解
- 角度来分析 腾讯 一些游客微通道系统问题 (一个)