Codeforces Round #236 (Div. 2) (全)
来源:互联网 发布:cad截图软件betterwmf 编辑:程序博客网 时间:2024/04/30 21:12
题目地址: http://codeforces.com/contest/402
A. Nuts
题意: 给你4个数k,a,b,v , k表示每一个盒子最多可以分成多少部分,a 表示一共多少个nuts,b表示一共多少个divisors (x个可以把 盒子分成x+1部分),v表示每一部分最多能放多少个nuts.
要把所有的nuts全部放到盒子中去,使用<=b个divisors,求 使用的盒子的数量最小。
就是 把b个divisors尽可能的 往开始的盒子里面放,之后 求b个nuts可以最少占用几个盒子 即可。
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>using namespace std;#define INF 1000000000int k,a,b,v;int main(){ scanf("%d%d%d%d",&k,&a,&b,&v); int xx=b/(k-1); int left=b-xx*(k-1); int ans=0; if(xx*v*k>=a) { ans=(a/(k*v)); if(a%(k*v)) ans++; } else if(xx*v*k+(left+1)*v>=a) ans=xx+1; else { ans=xx+1; int tmp=a-xx*v*k-(left+1)*v; ans+=((tmp/v)); if(tmp%v) ans++; } printf("%d\n",ans); return 0;}
B. Trees in a Row
题意: 开始给你n个树木的高度,可以进行 操作, 一次操作 是指 使得一棵树增加或者减小到任意整数高度,给你k , 要求进行某些操作后使得这些高度,形成等差数列,差值为k。
求最小的操作数,并且输出方案。 注意 一个树的高度不能为0!!!
直接暴力枚举每个树的高度 为正好不变 求其他 是否改变,求 最小的更改数目 就OK了。
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>using namespace std;#define INF 1000000000//typedef __int64 LL;#define N 1005int n,k;int num[N],fir;int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) { scanf("%d",&num[i]); } int ans=INF; for(int i=1;i<=n;i++) { int tmp=0; int mi=(num[i]-(i-1)*k); if(mi<=0) continue; for(int j=1;j<i;j++) { int mm=num[i]-(i-j)*k; if(mm!=num[j]) tmp++; } for(int j=i+1;j<=n;j++) { int mm=num[i]+(j-i)*k; if(mm!=num[j]) tmp++; } if(tmp<ans) { ans=tmp; fir=num[i]-(i-1)*k; } } printf("%d\n",ans); for(int i=1;i<=n;i++) { if(fir+(i-1)*k==num[i]) continue; if(fir+(i-1)*k>num[i]) printf("+ %d %d\n",i,abs(fir+(i-1)*k-num[i])); else printf("- %d %d\n",i,abs(num[i]-(fir+(i-1)*k))); } return 0;}
C. Searching for Graph
题意: 给你n 和p ,要你构造一个无向图,使得 一共有2*n+p条边,没有自回路和重边,对于任意选出的k个点,这k个点之间的 边的数目 <=2*k+p个
当初,看到过的人 写的比较快 就猜了一下,直接 依次 从 标号小的连接到 标号大的。事后证明是对的,确实如此可以,满足以上条件。
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>using namespace std;#define INF 1000000000//typedef __int64 LL;int t,n,p;int main(){ scanf("%d",&t); while(t--) { int cou=0; scanf("%d%d",&n,&p); for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { cou++; printf("%d %d\n",i,j); if(cou>=2*n+p) break; } if(cou>=2*n+p) break; } } return 0;}
D. Upgrading Array
题意:给你一个数列a,一些bad素数 b(除了这些之外的素数都是good 素数),可以对数列a,进行多次操作: 对a的前缀数组[1,r],求出他们的GCD,之后全部约去,得到一个新的数组。 之后每一个数有一个值,假设p是x的最小的素数因子,则 这个值f(1)=0; f(x)=f(x/p)+1 (如果p是good素数), f(x)=f(x/p)-1 (如果p是bad素数), 求 可以得到的 数值之和 的 最大值。
其实,不必在意最小的素数因子, 一个数的 价值= 分解后的 素数因子中 good的数目- bad的数目。
贪心进行求解 即可,求出 每个位置 i ,的 1~i中的 数 的 GCD,【之后从后往前】判断每个GCD的 价值,如果>0不约去,<0约去,这样肯定是最优的,因为这样的GCD因子 约去 对于之前的 数的 价值都会增加。从而总价值增加。
code:
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>#include<vector>#include<cmath>#include<map>#include<set>using namespace std;#define INF 1000000000#define MOD 1000000007#define N 50005#define M 32000bool ispri[M];int num[N],n,m,gc[N];set<int> bad;vector<int> prime;void pr(){for(int i=2;i<M;i++){if(!ispri[i]){prime.push_back(i);for(int j=2*i;j<M;j+=i)ispri[j]=1;}}}int gcd(int x,int y){if(!y) return x;return gcd(y,x%y);}int cal(int x){int ret=0;for(int i=0;i<prime.size() && prime[i]<=x;i++){int now=prime[i];int xx=1;if(bad.find(now)!=bad.end()) xx=-1; while(x%now==0){ret+=xx;x/=now;}}if(x>1){ if(bad.find(x)!=bad.end()) ret--; else ret++;}return ret;}int main(){pr();scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d",&num[i]);}int tmp;for(int i=1;i<=m;i++){scanf("%d",&tmp); bad.insert(tmp);}gc[1]=num[1];for(int i=2;i<=n;i++){gc[i]=gcd(gc[i-1],num[i]);}int tot=0;int last=1;for(int i=n;i>=1;i--){tmp=cal(gc[i]/last);if(tmp<0){last=gc[i];tot+=cal(num[i]/gc[i]);}else tot+=cal(num[i]/last);}printf("%d\n",tot); return 0;}
E. Strictly Positive Matrix
题意:给一个矩阵A,保证Aij大于等于0,并且Aii不全为0。问是否存在k使得A^k中的每个元素大于0
其实,可以看做 离散数学中的可到达矩阵 的 概念, 和图论联系起来,如果存在K使得 A^K中的每个元素>=0,就是 矩阵A代表的 图, 是一个 强连通图。
就是 判断 这个图 是否是强连通 即可。
Tarjan算法。可参考 https://www.byvoid.com/blog/scc-tarjan/
code :
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<string>#include<vector>#include<cmath>#include<stack>#include<set>using namespace std;#define INF 1000000000#define N 2005int n,tot,hh[N*N],dfn[N],low[N],flag,ad=0,ins[N],cou;struct node{int u,next;}edge[N*N];stack<int > s;void init(){tot=0;memset(hh,-1,sizeof(hh));memset(dfn,0,sizeof(dfn));memset(ins,0,sizeof(ins));}void add(int x,int y){edge[tot].u=y; edge[tot].next=hh[x];hh[x]=tot++;}void tar(int u){if(flag) return ;dfn[u]=low[u]=++ad;s.push(u);ins[u]=1;for(int i=hh[u];i!=-1;i=edge[i].next){int v=edge[i].u;// printf("%d \n",v);if(!dfn[v]){tar(v);low[u]=min(low[u],low[v]);}else if(ins[v]){low[u]=min(low[u],dfn[v]);}}if(dfn[u]==low[u]){int m=s.top(); s.pop();cou++;if(cou>1) { flag=1; return ;}ins[m]=0;while(m!=u){m=s.top(); s.pop(); ins[m]=0;}}}void sol(){cou=0; flag=0;for(int i=1;i<=n;i++){if(!dfn[i]){tar(i);if(flag){printf("NO\n"); return ;}}}printf("YES\n");}int main(){scanf("%d",&n);int tmp;init();for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){scanf("%d",&tmp);if(tmp){add(i,j);}}}int mark=0;sol(); return 0;}
- Codeforces Round #236 (Div. 2) (全)
- Codeforces Round #173 (Div. 2) <全>
- Codeforces Round #183 (Div. 2) <全>
- Codeforces Round #191 (Div. 2) <全>
- Codeforces Round #192 (Div. 2) <全>
- Codeforces Round #234 (Div. 2) <全>
- Codeforces Round #236 (Div. 2)
- Codeforces Round #236 (Div. 2)
- Codeforces Round #236 (Div. 2)
- Codeforces Round #323 (Div. 2) ABC题解(全是暴力)
- Codeforces Round #236 (Div. 2) A. Nuts
- Codeforces Round #236 (Div. 2)B
- Codeforces Round #236 (Div. 2)A
- Codeforces round #236Div.2--A;B
- Codeforces Round #236 (Div. 2)__Upgrading Array
- Codeforces Round #236 (Div. 2) A. Nuts
- Codeforces Round #236 (Div. 2)------A,B
- Codeforces Round #236 (Div. 2)(强联通)
- 循环结构中break、continue、return和exi()t的区别
- FilenameFilter总结
- JAVA学习笔记---第一天(李兴华)
- 494 - Kindergarten Counting Game
- java反射机制详解
- Codeforces Round #236 (Div. 2) (全)
- cocos2d-x scoket 解决方案
- 动态产生表格(节点创建)
- 旺财iOS版的设计思想
- 字符串中第一次出现的只出现一次的字符
- 画长方形
- ORACLE数值型函数
- linux 启动时,自动执行指令
- POJ 3378 Crazy Thairs(数据集中+DP+树状数组+高精度)