BC div2补题以及 复习模除 逆元__BestCoder Round #78 (div.2)
第一题没话说 智商欠费 加老柴辅导终于过了
需要在意的是数据范围为2的63次方-1 三个数相加肯定爆了
四边形的定义 任意边小于其余三边之和
换句话说就是 最长边小于其余三边之和
这样的话问题转化为 最长边依次减其余三边的结果是否小于等于0
还有一点是题目出现0边 即最小边不为0 想得太多反而把0也算为合法。。。。
问题只需要 sort一下 判断a[0]==0||a[3]-a[2]-a[1]-a[0]>=0 输出NO //存在0边且最大边大于其他边之和
第二题 好多种姿势 题目链接http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=683&pid=1002
官方题解
我们令dp[i][j]表示在前i个数中,选出若干个数使得它们的gcd为j的方案数,于是只需要枚举第i+1个数是否被选中来转移就可以了
令第i+1个数为v,当考虑dp[i][j]的时候,我们令$dp[i+1][j] += dp[i]j,dp[i+1][gcd(j,v)] += dp[i]j
复杂度O(N*MaxV) MaxV 为出现过的数的最大值
其实有O(MaxV *log(MaxV))的做法,我们考虑记f[i]表示从这些数中选择若干个数,使得他们的gcd是i的倍数的方案数。假如有K个数是i的倍数,则 f[i]=2^K-1,再用g[i]表示从这些数中选择若干个数,使得他们的gcd是i的方案数,则g[i]=f[i] - g[j] (对于所有j是i的倍数)。
由调和级数可以得到复杂度为O(MaxV *log(MaxV))
DP之二维数组转移
我们把dp[i][j]作为考虑了第i个数GCD为j的方案数
直接gcd会超时 所以我们打个表GCD
那么dp[i][j]+=dp[i-1][j]; dp[i][GCD[j][v[i]]]+=dp[i-1][j]; 然后就可以转移辣;
#include<cstdio>
#include<map>
//#include<bits/stdc++.h>
#include<vector>
#include<stack>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<queue>
#include<cstdlib>
#include<climits>
#define PI acos(-1.0)
#define INF 0x3fffffff
using namespace std;
typedef long long ll;
typedef __int64 int64;
const ll mood=1e9+;
const int64 Mod=;
const double eps=1e-;
const int N=;
const int MAXN=;
typedef int rl;
inline void r(rl&num){
num=;rl f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')num=num*+ch-'',ch=getchar();
num*=f;
}
int gcd(int a,int b)
{
return b==?a:gcd(b,a%b);
}
int v[N];
int GCD[N][N];
int64 dp[N][N];
int main()
{
for(int i=;i<;i++)
{
for(int j=;j<=i;j++)
{
GCD[i][j]=GCD[j][i]=gcd(i,j);
}
}
int ci;
r(ci);
while(ci--)
{
int n;
r(n);
int mx=-;
for(int i=;i<=n;i++)
{
r(v[i]);
mx=max(mx,v[i]);
dp[i][v[i]]=;
}
for(int i=;i<=n;i++)
{
for(int j=;j<=mx;j++)
{
dp[i][j]+=dp[i-][j];
dp[i][j]%=Mod;
dp[i][GCD[j][v[i]]]+=dp[i-][j];
dp[i][GCD[j][v[i]]]%=Mod;
}
}
int64 ans=; for(int i=;i<=mx;i++)
{ ans+=(dp[n][i]*i)%Mod;
ans%=Mod;
}
memset(dp,,sizeof(dp));
memset(v,,sizeof(v));
printf("%I64d\n",ans);
}
return ;
}
二维
仔细想了一下 觉得可以优化为滚动数组 试了好久不对 最后瞎蒙
每个数都多考虑了一次 所以/2需要乘逆元 正好1e8+7是素数
Mod为素数,那么还可以根据费马小定理得到逆元为 2的(Mod-2)次方%Mod
即除2等于乘2的(Mod-2)次方%Mod
所以加了一个快速幂 但是优化为滚动数组后 时间增加了一丢丢 但空间大幅度减少
| 16757862 | 2016-04-03 12:45:34 | Accepted | 5656 | 2511MS | 5504K | 1925 B | G++ | zxMrlc |
| 16755798 | 2016-04-03 00:36:10 | Accepted | 5656 | 2449MS | 13404K | 1722 B | G++ | zxMrlc |
但是姿势老感觉有问题 等wtw学长指点后我再改改 还有官方的第二个姿势还没有学会。。。衰
#include<cstdio>
#include<map>
//#include<bits/stdc++.h>
#include<vector>
#include<stack>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<queue>
#include<cstdlib>
#include<climits>
#define PI acos(-1.0)
#define INF 0x3fffffff
using namespace std;
typedef long long ll;
typedef __int64 int64;
const ll mood=1e9+;
const int64 Mod=;
const double eps=1e-;
const int N=;
const int MAXN=;
typedef int rl;
inline void r(rl&num){
num=;rl f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')num=num*+ch-'',ch=getchar();
num*=f;
}
int gcd(int a,int b)
{
return b==?a:gcd(b,a%b);
}
int v[N];
int GCD[N][N];
int64 dp[N];
int main()
{
int64 xx=Mod-;
int64 an=,t=;
while(xx>)
{
if(xx&) an*=t;
xx/=;
an%=Mod;
t*=t;
t%=Mod;
}
for(int i=;i<;i++)
{
for(int j=;j<=i;j++)
{
GCD[i][j]=GCD[j][i]=gcd(i,j);
}
} int ci;
r(ci);
while(ci--)
{
int n;
r(n);
int mx=-;
for(int i=;i<=n;i++)
{
r(v[i]);
mx=max(mx,v[i]);
} for(int i=;i<=n;i++)
{
dp[v[i]]++;
for(int j=;j<=mx;j++)
{
// dp[i][j]+=dp[i-1][j];
dp[j]%=Mod;
dp[GCD[j][v[i]]]+=dp[j];
dp[GCD[j][v[i]]]%=Mod;
}
}
int64 ans=;
//for(int i=1;i<=mx;i++) cout<<dp[i]<<endl;
for(int i=;i<=mx;i++)
{ ans+=(dp[i]*i)%Mod;
ans%=Mod;
}
memset(dp,,sizeof(dp));
memset(v,,sizeof(v));
printf("%I64d\n",ans*an%Mod);
}
return ;
}
滚动数组
我们每次加入的数据会导致翻倍 所以刚才改为加完/2;
因为添加的v[i]导致的影响就是 当前位置dp[v[i]]多1 即方案数多了选自己的 所以在循环结尾-1就ok了 。。。根本不需要模除 但时间特么变大了
还是有点模糊的 不太清楚到底怎么回事。
| 16758163 | 2016-04-03 13:17:49 | Accepted | 5656 | 2636MS | 5504K | 1730 B | G++ | zxMrlc |
#include<cstdio>
#include<map>
//#include<bits/stdc++.h>
#include<vector>
#include<stack>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
#include<queue>
#include<cstdlib>
#include<climits>
#define PI acos(-1.0)
#define INF 0x3fffffff
using namespace std;
typedef long long ll;
typedef __int64 int64;
const ll mood=1e9+;
const int64 Mod=;
const double eps=1e-;
const int N=;
const int MAXN=;
typedef int rl;
inline void r(rl&num){
num=;rl f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')num=num*+ch-'',ch=getchar();
num*=f;
}
int gcd(int a,int b)
{
return b==?a:gcd(b,a%b);
}
int v[N];
int GCD[N][N];
int64 dp[N];
int main()
{
for(int i=;i<;i++)
{
for(int j=;j<=i;j++)
{
GCD[i][j]=GCD[j][i]=gcd(i,j);
}
} int ci;
r(ci);
while(ci--)
{
int n;
r(n);
int mx=-;
for(int i=;i<=n;i++)
{
r(v[i]);
mx=max(mx,v[i]);
} for(int i=;i<=n;i++)
{
dp[v[i]]++;
for(int j=;j<=mx;j++)
{
// dp[i][j]+=dp[i-1][j];
dp[j]%=Mod;
dp[GCD[j][v[i]]]+=dp[j];
dp[GCD[j][v[i]]]%=Mod;
}
dp[v[i]]--;
}
int64 ans=;
for(int i=;i<=mx;i++)
{ ans+=(dp[i]*i)%Mod;
ans%=Mod;
}
memset(dp,,sizeof(dp));
memset(v,,sizeof(v));
printf("%I64d\n",ans%Mod);
}
return ;
}
滚动第二次优化
BC div2补题以及 复习模除 逆元__BestCoder Round #78 (div.2)的更多相关文章
- codeforces round 422 div2 补题 CF 822 A-F
A I'm bored with life 水题 #include<bits/stdc++.h> using namespace std; typedef long long int LL ...
- codeforces round 421 div2 补题 CF 820 A-E
A Mister B and Book Reading O(n)暴力即可 #include<bits/stdc++.h> using namespace std; typedef lon ...
- Codeforces round 419 div2 补题 CF 816 A-E
A Karen and Morning 水题 注意进位即可 #include<bits/stdc++.h> using namespace std; typedef long long i ...
- codeforces 447 A-E div2 补题
A DZY Loves Hash 水题 #include<iostream> #include<cstdio> #include<cstdlib> #include ...
- codeforces round 418 div2 补题 CF 814 A-E
A An abandoned sentiment from past 水题 #include<bits/stdc++.h> using namespace std; int a[300], ...
- codeforces round 417 div2 补题 CF 812 A-E
A Sagheer and Crossroads 水题略过(然而被Hack了 以后要更加谨慎) #include<bits/stdc++.h> using namespace std; i ...
- codeforces round 416 div2 补题 CF 811 A B C D E
A. Vladik and Courtesy 水题略过 #include<cstdio> #include<cstdlib> #include<cmath> usi ...
- codeforces round 420 div2 补题 CF 821 A-E
A Okabe and Future Gadget Laboratory 暴力 #include<bits/stdc++.h> using namespace std; typedef l ...
- 2018 HDU多校第三场赛后补题
2018 HDU多校第三场赛后补题 从易到难来写吧,其中题意有些直接摘了Claris的,数据范围是就不标了. 如果需要可以去hdu题库里找.题号是6319 - 6331. L. Visual Cube ...
随机推荐
- PHP实用小程序(三)
<HTML> <HEAD> <TITLE>给数组增加元素</TITLE> </HEAD> <? $Cities[] = "& ...
- UVa 1645 Count (递推,数论)
题意:给定一棵 n 个结点的有根树,使得每个深度中所有结点的子结点数相同.求多棵这样的树. 析:首先这棵树是有根的,那么肯定有一个根结点,然后剩下的再看能不能再分成深度相同的子树,也就是说是不是它的约 ...
- JAVA基础--JAVA API集合框架(ArrayList、HashSet、HashMap使用)14
一.集合Collection 1. 集合介绍 变量:表示的内存中的一个空间,只能保存确定类型的单个数据 数组:表示的是内存中的多个连续的空间,这些空间中可以存储多个同类型的数据. 后期继续学习面向对象 ...
- 怎样使一个INPUT框里的文字在框被点击后自动全选或清除?
$("#smsContent").focus(function(){ this.select(); }); <input name="keywords" ...
- Lightoj 1082【RMQ】
这里很low地写了个线段树... #include <bits/stdc++.h> using namespace std; typedef long long LL; const int ...
- Mecanim动画系统 - 在角色上使用Mask 叠加动画层
http://www.narkii.com/club/thread-305706-1.html 2013-10-9 01:15 上传 下载附件 (78.65 KB) 导读:五分钟了解Mecanim角色 ...
- 洛谷P1291 百事世界杯之旅
P1291 百事世界杯之旅 题目描述 “……在2002年6月之前购买的百事任何饮料的瓶盖上都会有一个百事球星的名字.只要凑齐所有百事球星的名字,就可参加百事世界杯之旅的抽奖活动,获得球星背包,随声听, ...
- 2012 Noip提高组 Day2
1265. [NOIP2012] 同余方程 ★☆ 输入文件:mod.in 输出文件:mod.out 简单对比时间限制:1 s 内存限制:128 MB [题目描述] 求关于 x 的同余方 ...
- [Xcode 实际操作]八、网络与多线程-(22)使用GCD多线程技术异步下载图片
目录:[Swift]Xcode实际操作 本文将演示如何使用使用GCD多线程技术异步下载图片. Grand Central Dispatch(GCD) 是 Apple 开发的一个多核编程的较新的解决方法 ...
- 新建Podfile命令
接下来,你需要建立一个主工程.建立成功以后,再次启动终端, 利用cd命令进入到工程文件夹内,此时需要创建一个特殊的文本文件,命令如下: 命令: touch Podfile 创建 命令: open -e ...