AcWing基础算法课Level-3 第一讲 基础算法
Posted 小哈里
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AcWing基础算法课Level-3 第一讲 基础算法相关的知识,希望对你有一定的参考价值。
AcWing基础算法课Level-3 第一讲 基础算法
位运算
AcWing 90. 64位整数乘法761人打卡
递推与递归
AcWing 95. 费解的开关520人打卡
AcWing 97. 约数之和379人打卡
AcWing 98. 分形之城268人打卡
前缀和与差分
AcWing 99. 激光炸弹460人打卡
AcWing 100. 增减序列407人打卡
二分
AcWing 102. 最佳牛围栏423人打卡
AcWing 113. 特殊排序280人打卡
排序
AcWing 105. 七夕祭262人打卡
AcWing 106. 动态中位数326人打卡
AcWing 107. 超快速排序328人打卡
RMQ
AcWing 1273. 天才的记忆
代码
AcWing 90. 64位整数乘法761人
//将b的每一位拆成二进制与a相应的幂相乘
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 100010;
int main(){
LL a, b, p, ans=0;
cin>>a>>b>>p;
while(b){
if(b&1)ans = (ans+a)%p;
b >>= 1;
a = a*2%p;
}
cout<<ans<<"\\n";
return 0;
}
AcWing 95. 费解的开关520人
//题意:给出一组5*5的开关,每次可以改变一个点和它上下左右的开关,判断能否6步内让所有灯点亮,输出步数。
//思路:可以发现性质,如果确定了第i行的方案的话,那么后面的行数都可以依此递推,因此只需要枚举第一行即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int a[10][10], b[10][10], ans;
void change(int x, int y){
b[x][y] ^= 1;
b[x-1][y]^=1;
b[x][y+1]^=1;
b[x][y-1]^=1;
b[x+1][y]^=1;
}
int check(){
for(int i = 1; i <= 5; i++)
for(int j = 1; j <= 5; j++)
if(!b[i][j])return false;
return true;
}
int calc(){//求最小步数
ans = 1e9+10;
for(int i = 0; i < (1<<5); i++){
int tmp = 0;
memcpy(b, a, sizeof(a));
for(int j = 1; j <= 5; j++){//枚举第1行改变哪几个
if(i>>(j-1) & 1){
change(1,j);
tmp++;
}
}
for(int j = 1; j <= 4; j++){//按照现在的第一行计算
for(int k = 1; k <= 5; k++){
if(!b[j][k]){
change(j+1,k);
tmp++;
}
}
}
if(check())ans = min(ans, tmp);
}
return ans;
}
int main(){
int T; cin>>T;
while(T--){
getchar();
for(int i = 1; i <= 5; i++){
for(int j = 1; j <= 5; j++){
a[i][j] = getchar()-'0';
}
getchar();
}
if(calc()<=6){
cout<<ans<<"\\n";
}else{
cout<<"-1\\n";
}
}
return 0;
}
AcWing 97. 约数之和379人
//题意:求出A^B的所有约数和膜9901的值,A,B<5e7
//思路:约数之和(p1^0+p1^1+…+p1^c1)*...*(pk^0+pk^1+…+pk^ck), B的所有约数和膜9901的值,B次方意味着c1,c2,都乘以B
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 9901;
LL mpow(LL a, LL x) {
if(x==0)return 1;
LL t = mpow(a, x>>1);
if(x%2==0)return t*t%mod;
return t*t%mod*a%mod;
}
LL sum(int p, int c){//sum=p1^0+p1^1+…+p1^c1
if(c==0){
return 1;
}else if(c%2==1){
return (1+mpow(p,c/2+1))*sum(p,c/2)%mod;
}else{
return (p%mod*sum(p,c-1)+1)%mod;
}
}
int main(){
int a, b; cin>>a>>b;
if(a==0){cout<<"0\\n"; return 0;}
int ans = 1;
for(int i = 2; i <= a; i++){
int s = 0;
while(a%i==0){//pi^ci==i^s
s++;
a/=i;
}
if(s)ans = ans*sum(i,s*b)%mod;//sum=(sum*p+1)%mod;
}
cout<<ans<<"\\n";
return 0;
}
AcWing 98. 分形之城268人
//题意:等级n的城市有2^2n个街区,按照图中的方式旋转相连,求编号a,b的街区之间的距离。
//思路:可以发现规律,左上角为顺时针旋转90即(x,y)变位(y,x)。左下角逆时针旋转90且水平翻转,即变为(-y,-x)。右上角和右下角没有旋转,只是平移。知道转移之后递归计算。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PLL;
PLL calc(LL n, LL m){
if(n==0)return make_pair(0,0);
LL len = 1LL<<(n-1), cnt = 1LL<<(2*n-2);//n-1级图的边长和街区数
PLL pos = calc(n-1,m%cnt);//递归计算n-1级时的坐标
LL x = pos.first, y = pos.second;
LL z = m/cnt;//判断所在区域并推出当前坐标
if(z==0)return make_pair(y,x);
if(z==1)return make_pair(x,y+len);
if(z==2)return make_pair(x+len,y+len);
return make_pair(2*len-1-y,len-1-x);
}
int main(){
int T; cin>>T;
while(T--){
LL n, a, b; cin>>n>>a>>b;
PLL x = calc(n,a-1);
PLL y = calc(n,b-1);
LL dx=x.first-y.first, dy=x.second-y.second;
printf("%.0lf\\n", sqrt(dx*dx+dy*dy)*10);
}
return 0;
}
AcWing 99. 激光炸弹460人
//题意:给出n个点的坐标和价值wi,求边长为R的正方形最多可以覆盖的价值
//思路:维护二维前缀和,扫一遍统计即可
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5050;
int s[maxn][maxn];
int main(){
int n, r; cin>>n>>r;
r = min(r, 5010);
for(int i = 1; i <= n; i++){
int x, y, w; cin>>x>>y>>w;
s[++x][++y] += w;//WA, 边界
}
for(int i = 1; i <= 5010; i++){
for(int j = 1; j <= 5010; j++){
s[i][j] += s[i-1][j]+s[i][j-1]-s[i-1][j-1];
}
}
int ans = -1e9+10;
for(int i = 1; i <= 5010; i++){
for(int j = 1; j <= 5010; j++){
int x1=i,y1=j, x2=min(5010,i+r-1), y2=min(5010,j+r-1);
ans = max(ans, s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1]);
}
}
cout<<ans<<"\\n";
return 0;
}
AcWing 100. 增减序列407人
//题意:给出长为n的数列,每次可以对[l,r]+1或-1,求最少多少次让所有数都一样,且最少次数下可能的数列有几种。
//思路:
//+ 让序列相同,等价于让差分序列[2,n]全为0,b1有几种,答案就有几种。
//+ 每次可以修改b[l]+=d,b[r+1]-=d,因为不关注方案只要结果而且一定能恰好。所以贪心的每次选bi(>0)和bj(<0)配对,负数增加,正数减少,可以最快地到达全为0的状态,无法配对的和b1配,
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+10;
LL a[maxn], c[maxn];
int main(){
LL n; cin>>n;
for(int i = 1; i <= n; i++){
cin>>a[i];
}
LL z=0, f=0;
for(int i = 2; i <= n; i++){
c[i] = a[i]-a[i-1];
if(c[i]>0)z += c[i];
else f -= c[i];
}
cout<<max(z,f)<<"\\n"<<abs(z-f)+1<<"\\n";
return 0;
}
AcWing 102. 最佳牛围栏423人
//题意:n块田分别有ai头牛,选择其中某一连续大于等于F块地的部分,令其中牛的总数的平均值最大,求最大平均值*1000。
//题意:n个数,求所有连续且满足长度>=F的子序列的平均值的最大值
//思路:最优化问题,想到二分平均值,判断是否可行。判断时都减去avg,若区间前缀和>=0则成立,因为长度不定,所以扫描区间时用双指针。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+10;
int n, f, a[maxn]; double s[maxn];
bool check(double avg){
for(int i = 1; i <= n; i++)
s[i] = s[i-1]+a[i]-avg;
double mi = 0;
int l = 0, r = f;
while(r <= n){
mi = min(mi, s[l]);
if(s[r]-mi >= 0)return true;
l++; r++;
}
return false;
}
int main(){
cin>>n>>f;
int mx = 0;
for(int i = 1; i <= n; i++){
cin>>a[i]; mx = max(mx, a[i]);
}
double l = 0, r = mx;
while(r-l >= 1e-5){
double mid = (l+r)/2;
if(check(mid))l = mid;
else r = mid;
}
cout<<(int)(r*1000)<<"\\n";
return 0;
}
AcWing 113. 特殊排序280人
//题意:n个元素(1-1000),任意两个之间的大小关系确定(提供交互查询函数),不存在元素相等,通过不超过10000比较对数组进行排序。
//思路:归并排序满足"元素大小关系不具传递性",直接sort。
// 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>vc;
for(int i = 1; i <= N; i++)
vc.push_back(i);
stable_sort(vc.begin(), vc.end(), compare);
return vc;
}
};
AcWing 105. 七夕祭262人
//题意:n*m个摊点,其中T个感兴趣。求是否能通过交换相邻点使各行各列感兴趣的摊点一样多,如果能,输出最少交换次数。
//思路:可以发现性质,每次交换任意相邻两数,只会改变一行或一列的摊数,而不会同时改变行与列,因此可以行列分开做,成为纸牌均分问题。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 100010;
int n, m, t;
int b[maxn], c[maxn], s[maxn];
LL calc(int a[], int n){
for(int i = 1; i <= n; i++){
a[i] -= a[0]/n;
s[i] = s[i-1]+a[i];以上是关于AcWing基础算法课Level-3 第一讲 基础算法的主要内容,如果未能解决你的问题,请参考以下文章