Codeforces Round #196 contest/338 div1

来源:互联网 发布:区域电网排放因子数据 编辑:程序博客网 时间:2024/06/05 06:08

problem A. Quiz

YY一下,贪心就行。

对于F[N] = 2*( F[N - 1] + K)的计算,可以:

1、推出等比数列公式,然后用整数快速幂。

2、矩阵快速幂计算

3、F[N] + 2*K = 2 * (F[N - 1] + 2*K)。设a[N] = F[N] + 2*K,转换递归式,然后整数快速幂。

都可以求解。

#include <limits.h>#include <stdio.h>#include <string.h>#include <math.h>#include <stdlib.h>#include <algorithm>#include <iostream>using namespace std;#define llg long longtemplate<typename T> inline void checkMin(T& a, T b) { if (a > b) a = b; }template<typename T> inline void checkMax(T& a, T b) { if (a < b) a = b; }template<class T> inline T Min(T x,T y){return (x>y?y:x);} template<class T> inline T Max(T x,T y){return (x<y?y:x);}llg mod = 1000000009;llg n,m,k;llg ans;llg quickpow(llg a,llg b){llg ans = 1;while(b){if(b&1)ans = (ans * a)%mod;a = (a * a)%mod;b = b>>1;}return ans;}int main(){cin>>n>>m>>k;ans = 0;llg wa = n - m;llg r = (n - m) * k;if(r >= n)  ans = m;else{llg nn = n - r;llg a = nn / k;llg b = nn % k;ans = ((quickpow(2,a + 1) - 2 + mod)%mod)*k%mod;ans += b + wa*(k - 1)%mod;ans %= mod;}cout<<ans<<endl;return 0;}


problem B. Book of Evil

赛后才过的,很明显的树形DP。

推荐可以先做弱化版本hdu 2196。

思想关键在于对dpdown,dpup的理解。

第一个dfs1:父亲问儿子们:儿子们,从你们往下走,碰到最远的evil有多远啊?从各个儿子回答中,得出dpdown[ father ][ 0 ]即自己距离evil最远的距离,dpdown[ father ][ 1]即自己距离evil次最远的距离。

第二个dfs2:儿子跟父亲说:父亲,我往你这边走,可以到达evil的最远距离是多少啊?更新dpup[i]。


#include<iostream>#include<cstdio>#include<cstring>#include<vector>using namespace std;#define maxn 100010struct tree{vector<int> child;}node[maxn];int n,m,d;int dpdown[maxn][2];/*0 is longest 1 is second*/int dpup[maxn];int next[maxn];/*longest distance next*/bool vis[maxn];bool evil[maxn];void addedge(int x,int y){node[x].child.push_back(y);node[y].child.push_back(x);}int mymax(int x,int y){return x>y?x:y;}void dfs1(int fa,int now){vis[now] = true;dpdown[now][0] = dpdown[now][1] = -1;dpup[now] = -1;next[now] = 0;if(evil[now])dpdown[now][0] = 0;for(int i = 0;i < node[now].child.size();i++){int son = node[now].child[i];if(vis[son] || son == fa)continue;dfs1(now,son);if(dpdown[son][0] >= 0){/*除去-1*/if(dpdown[son][0] + 1 >= dpdown[now][0]){dpdown[now][1] = mymax(dpdown[now][0],dpdown[now][1]);dpdown[now][0] = dpdown[son][0] + 1;next[now] = son;}else{dpdown[now][1] = mymax(dpdown[son][0] + 1,dpdown[now][1]);}}}}void dfs2(int fa,int now){for(int i = 0;i < node[now].child.size();i++){int son = node[now].child[i];if(son == fa)continue;if(dpup[now] >= 0)dpup[son] = dpup[now] + 1;if(next[now] != son && dpdown[now][0] >= 0){dpup[son] = mymax(dpup[son],dpdown[now][0] + 1);}else if(dpdown[now][1] >= 0){dpup[son] = mymax(dpup[son],dpdown[now][1] + 1);}dfs2(now,son);}}int main(){scanf("%d %d %d",&n,&m,&d);for(int i = 1;i <= m;i++){int x;scanf("%d",&x);evil[x] = true;}for(int i = 1;i <= n - 1;i++){int x,y;scanf("%d %d",&x,&y);addedge(x,y);}dfs1(-1,1);dfs2(-1,1);int ans = 0;for(int i = 1;i <= n;i++){if(dpdown[i][0] <= d && dpup[i] <= d)  ans++;}printf("%d\n",ans);return 0;}

problem C. Divisor Tree

暴力枚举树。。

每个数字有这样几个去向:

1、a1作为a2的一个因子,即“有father的数字"这一类型。

2、a1不作为任何数字的因子,那么可以将这些类型的数字:一、素因子个数直接加到答案,二、最后合并为根,一个就不需要合并了。


#include <limits.h>#include <stdio.h>#include <string.h>#include <math.h>#include <stdlib.h>#include <algorithm>#include <iostream>#include <limits.h>using namespace std;#define llg long longtemplate<typename T> inline void checkMin(T& a, T b) { if (a > b) a = b; }template<typename T> inline void checkMax(T& a, T b) { if (a < b) a = b; }template<class T> inline T Min(T x,T y){return (x>y?y:x);} template<class T> inline T Max(T x,T y){return (x<y?y:x);}#define maxn 20llg a[maxn],ta[maxn];int fa[maxn],cnt[maxn];int n;int ans = INT_MAX;void ok(){int twotree = 0;int tans = 0;for(int i = 1;i <= n;i++){if(fa[i] == 0){twotree++;tans += cnt[i];}if(cnt[i] == 1)/*不要算自己*/  tans--;}tans += n;if(twotree >= 2)tans++;if(tans < ans)ans = tans;}void dfs(int now){if(now == n){ok();return ;}for(int i = now+1;i <= n;i++){if(ta[i]%a[now] == 0){/*被用来当作因子*/ta[i] /= a[now];fa[now] = i;dfs(now + 1);ta[i] *= a[now];}}fa[now] = 0;//不被任何当作因子,即最后多棵树合并dfs(now + 1);}int main(){cin>>n;for(int i = 1;i <= n;i++){cin>>a[i];}sort(a+1,a+1+n);for(int i = 1;i <= n;i++)  ta[i] = a[i];for(int i = 1;i <= n;i++){llg tmp = a[i];for(llg k = 2;k*k <= a[i];k++)  while(tmp%k == 0)  {  cnt[i]++;  tmp /= k;  }if(tmp > 1)cnt[i]++;}dfs(1);cout<<ans<<endl;return 0;}





原创粉丝点击