复健\(Day3\)
一些基础的算法(模板)
\(1.\)位运算
进行状压\(DP\)时常用到位运算
\(64\)位整数乘法
https://www.acwing.com/problem/content/92/
#include<iostream>
#include<cstdio>
#define LL long long
using namespace std;
int main()
{
LL a,b,p;
cin>>a>>b>>p;
LL res=0;
while(b)
{
if(b&1) res=(res+a)%p;
a=(a<<1)%p;
b>>=1;
}
printf("%lld\n",res);
return 0;
}
快速幂
https://www.acwing.com/problem/content/91/
#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
using namespace std;
int main()
{
LL a,b,p;
cin>>a>>b>>p;
LL res=1%p;
while(b)
{
if(b&1) res=res%p*a%p;
a=a*a%p;
b>>=1;
}
return res;
printf("%lld\n",res);
return 0;
}
最短\(Hamiton\)路径
https://www.acwing.com/problem/content/93/
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 20
using namespace std;
int dis[N][N];
int dp[1<<N][N];
int main()
{
memset(dp,0x3f,sizeof(dp));
int n;
cin>>n;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>dis[i][j];
}
}
dp[1][0]=0;
for(int i=0;i<(1<<n);i++)//注意枚举顺序,最外层枚举为走过的状态
{
for(int j=0;j<n;j++)
{
if(i&(1<<j))
{
for(int k=0;k<n;k++)
{
if(j!=k)
{
dp[i][j]=min(dp[i][j],dp[i^(1<<j)][k]+dis[k][j]);
}
}
}
}
}
printf("%d\n",dp[(1<<n)-1][n-1]);
return 0;
}
\(2.\)二分
https://www.acwing.com/blog/content/2112/
对于左边红色区间的情况为
while(l<r)
{
int mid=(l+r+1)>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
对于右边绿色区间的情况为
while(l<r)
{
int mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
题目
\(1.Acwing102\)
https://www.acwing.com/problem/content/104/
向下取整函数\(floor\),\(double\) \(floor\)\((double\) \(arg)\),向上取整函数\(ceil\),用法与\(floor\)相同
#include<iostream>
#include<cstdio>
#include<cmath>
#define EPS 1e-5
#define maxn 100010
using namespace std;
int n,F;
int s[maxn];
double sum[maxn];
int Min(int a,int b)
{
return a>b?b:a;
}
int Max(int a,int b)
{
return a>b?a:b;
}
bool check(double ans)//双指针做法
{
for(int i=1;i<=n;i++)
{
sum[i]=sum[i-1]+s[i]-ans;
}
double minv=0;
for(int i=0,j=F;j<=n;i++,j++)
{
minv=min(minv,sum[i]);
if(sum[j]-minv>=0) return true;
}
return false;
}
int main()
{
cin>>n>>F;
double l=2000.0,r=1.0;
for(int i=1;i<=n;i++)
{
cin>>s[i];
l=Min(l,s[i]);
r=Max(r,s[i]);
}
while(r-l>EPS)
{
double mid=(l+r)/2.0;
if(check(mid)) l=mid;
else r=mid;
}
printf("%d\n",int(r*1000));
return 0;
}
这道题要求我们找到一段长度大于等于\(F\)的区间,这段区间里牛的平均数要使得其最大
首先我们可以考虑到采用二重循环,枚举区间长度(大于等于F)以及起点,这样的时间复杂度是略小于\(O(n\ ^2)\)(在前缀和预处理的情况下)
我们思考要如何优化,在前缀和上考虑进行处理。平均数有一个很明显的性质,某个数减去平均数如果大于\(0\),那么它本身就是大于平均数的,若小于\(0\)就是小于平均数的。因此我们用\(sum[i]\)记录\(s[1]-avg+s[2]-avg+s[3]-avg+...+s[i]-avg\)。
然后我们用两个指针\(i\)和\(j\),我们初始化\(i=0,j=F\),然后每次循环都\(i++,j++\)这样我们就可以保证\(i\)和\(j\)之间的距离始终保持为\(F\).
\(sum[j]-sum[i]\geqslant0\)时显然这一段的数减去平均大于等于\(0\),也即满足平均值大于等与该二分的答案,这样是考虑了长度为\(F\)的区间,而对于大于\(F\)的区间,我们又用一个\(minv\)记录从\(1\)至\(i\)的过程中\(sum[i]\)的最小值,这是最优的一个最小值,当我们\(sum[j]-minv\geqslant0\)时,那么我们的平均值就满足条件了并且保证了区间长度大于等于\(F\)了
这样\(check\)函数就优化成了\(O(n)\)的复杂度了
\(2.Acwing113\)
https://www.acwing.com/problem/content/115/
关于交互式问题
// Forward declaration of compare API.
// bool compare(int a, int b);
// return bool means whether a is less than b.
class Solution {
public:
vector<int> specialSort(int N) {
vector<int> v;
v.push_back(1);//将1装入v中,便于比较
for(int i=2;i<=N;i++)
{
int l=0,r=v.size()-1;
while(l<r)//找到第一个小于i的位置r
{
int mid=(l+r+1)>>1;//这里注意是l+r+1>>1
if(compare(v[mid],i)) l=mid;//v[mid]<i
else r=mid-1;
}
v.push_back(i);//把i放在v的最后一个位置
for(int j=v.size()-2;j>r;j--)//将i放在r+1的位置,然后把原本在r+1以及以后的数都往后移一位
{
swap(v[j],v[j+1]);
}
if(compare(i,v[r])) swap(v[r],v[r+1]);//i可能是最小的元素,v[r]仍然大于i,故这个时候我们做一个特殊判断
}
return v;
}
};
注意到我们这里的二分部分给的边界条件是\(l<r\),然后\(mid\)的计算式\((l+r+1)>>1\)
\(3.[USACO\) \(2009\) \(Dec\) \(S]Music\) \(Notes\)
https://ac.nowcoder.com/acm/contest/22353/A
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define maxn 50010
using namespace std;
int n,q,b[maxn];
int T[maxn];//记录开始时间
int query(int t)
{
int l=1,r=n;
while(l<r)
{
int mid=(l+r+1)>>1;
if(T[mid]>t) r=mid-1;
else l=mid;
}
return l;
}
int main()
{
cin>>n>>q;
for(int i=1;i<=n;i++)
{
cin>>b[i];
T[i]=T[i-1]+b[i-1];
}
while(q--)
{
int t;
cin>>t;
printf("%d\n",query(t));
}
return 0;
}
这道题需分清楚是我们二分里的哪种情况,因为T记录起始时间,所以当某个编号的起始时间大于\(t\)的时候\(mid\)一定不是最后的答案,故\(r\)为\(mid\)往前移一位
实际上我们的二分有很多种写法,也不必拘泥于这两种
\(3.\)排序
https://www.acwing.com/problem/content/description/109/
超快速排序
\(4.\)高精度
\(substr\)截取函数的用法:\(string\)型变量\(a\)的\(a.substr(n)\)指从\(a[1]\)一直截取至最后
高精度加减法模板
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
int compare(vector<int>& A,vector<int>& B)
{
if(A.size()<B.size()) return -1;
if(A.size()>B.size()) return 1;
for(int i=A.size()-1;i>=0;i--)
{
if(A[i]>B[i]) return 1;
else if(A[i]<B[i]) return -1;
}
return 0;
}
vector<int> add(vector<int>& A,vector<int>& B)
{
if(A.size()<B.size()) return add(B,A);
vector<int> C;
int t=0;
for(int i=0;i<A.size();i++)
{
t+=A[i];
if(i<B.size()) t+=B[i];
C.push_back(t%10);
t/=10;
}
if(t) C.push_back(t);
return C;
}
vector<int> sub(vector<int>& A,vector<int>& B)
{
if(compare(A,B)<0)
{
printf("-");
return sub(B,A);
}
vector<int> C;
int t=0;
for(int i=0;i<A.size();i++)
{
t+=A[i];
if(i<B.size()) t-=B[i];
C.push_back((t+10)%10);
if(t<0) t=-1;
else t=0;
}
while(C.size()>1&&C.back()==0) C.pop_back();
return C;
}
void print(vector<int> A)
{
for(int i=A.size()-1;i>=0;i--) printf("%d",A[i]);
printf("\n");
}
int main()
{
string a,b;
cin>>a>>b;
vector<int> A,B;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
print(add(A,B));
print(sub(A,B));
return 0;
}
高精度乘法模板
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
vector<int> mul(vector<int>& A,vector<int>& B)
{
vector<int> C(A.size()+B.size());
for(int i=0;i<A.size();i++)
for(int j=0;j<B.size();j++)
C[i+j]+=A[i]*B[j];
int t=0;
for(int i=0;i<C.size();i++)
{
t+=C[i];
C[i]=t%10;
t/=10;
}
while(C.size()>1&&C.back()==0) C.pop_back();
return C;
}
void print(vector<int> A)
{
for(int i=A.size()-1;i>=0;i--) printf("%d",A[i]);
}
int main()
{
string a,b;
cin>>a>>b;
vector<int> A,B;
for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0');
for(int i=b.size()-1;i>=0;i--) B.push_back(b[i]-'0');
print(mul(A,B));
return 0;
}
标签:return,int,基础,mid,算法,vector,include,size
From: https://www.cnblogs.com/iwillenter-top1/p/17603293.html