2025.2.3 想到啥写啥的寒假笔记(1)

  1. 二维差分(容斥)
//左上(q,w)到右下(e,r)范围内+1
++a[q][w];
--a[q][r+1];
--a[e+1][w];
++a[e+1][r+1];
//求二维前缀和
for(ll i=1;i<=n;i++){
	for(ll j=1;j<=n;j++){
		a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
	}
}
  1. P1835
    思路: [L,R] 中最大质因数不超过\(\sqrt(R)\),筛出[1,\(\sqrt(R)\)]的质数,再筛出[L,R]的合数,相减即答案
    技巧: 数组中 [L,R] 通过 i-L 映射到 [0,L-R],埃氏筛

  2. C - Strange Bank abc099
    一家银行只能取1,\(6^x\),\(9^x\)的钱,问若想要取n元(1e5),最小的取钱次数是多少。
    因为上限1e5,可以取钱的面值总情况可以预先枚举1,6,9,36,81......
    dp[x]表示,取x元的最小取钱次数,dp[x]=min{dp[x-i]+1},i为上面枚举的不大于x的面值
    很奇怪,意识不到是线性dp的话怎么也写不出来,意识到后就会写得很快,可能我和dp还不太熟。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll inf=0x3f3f3f3f3f3f3f3f;
vector<ll> a;
ll num[100005];
ll n;
void solve();

void solve(){
	cin>>n;
	a.push_back(1);
	for(ll res=6;res<=n;res*=6){
		a.push_back(res);
	}
	for(ll res=9;res<=n;res*=9){
		a.push_back(res);
	}
	sort(a.begin(),a.end());

	for(ll i=1;i<=n;i++) num[i]=inf;
	for(ll i=1;i<=n;i++){
		for(ll& j:a){
			if(i-j<0) break;
			num[i]=min(num[i],num[i-j]+1);
		}
	}
	cout<<num[n]<<'\n';
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	
	ll t=1;
	// cin>>t;
	while(t--){
		solve();
	}
	return 0;
}
  1. D. Patisserie ABC (400)
    n个蛋糕有"beauty", "tastiness","popularity"三个属性(可以是负数),问从中取出m个,各个属性取绝对值后求和的最大值是多少
    枚举000-->111 (0到7),0表示该属性取绝对值之前是负数,1为正数。
    若取绝对值之前是正数,则正数为总值做贡献,负数拖后腿,即要加上某属性值
    若取绝对值之前是负数,则负数为总值做贡献,正数拖后腿,即要减去某属性值
    最后将和排序,取最大的m个即可
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll inf=0x3f3f3f3f3f3f3f3f;
ll n,m;
ll a[1005][3]; //1:正 0:负

void solve();

void solve(){
	cin>>n>>m;
	for(ll i=1;i<=n;i++){
		for(ll j=0;j<3;j++){
			cin>>a[i][j];
		}
	}
	ll ans=0;
	for(ll i=0;i<8;i++){
		ll sum[1005];
		for(ll j=1;j<=n;j++){
			sum[j]=0;
			for(ll k=0;k<3;k++){
				if((i>>k) & 1) sum[j]+=a[j][k];
				else sum[j]-=a[j][k];
			}
		}
		sort(sum+1,sum+n+1);
		ll temp=0;
		for(ll i=n;i>n-m;i--){
			temp+=sum[i];
		}
		ans=max(temp,ans);
	}
	cout<<ans<<'\n';
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	
	ll t=1;
	// cin>>t;
	while(t--){
		solve();
	}
	return 0;
}
  1. G. Shuffling Songs
    题意:有n首歌,每首歌有类型genre和作者writer两个属性,需要建立一个播放列表,列表中相邻的歌需要至少有一个属性相同,问列表最大有多少首歌
    n最大才16,疑似旅行商(神秘第六感),但是没细想
    后来想用图论写,一开始以为题目等效于最大连通图的大小,写完后过样例但是WA5,想了想觉得应该是因为播放列表有前后关系,比如a和b连,a和c连,但是a后面只能接一首歌,b和c可能不会全选。
    后来用dfs求x点后最长链的个数,过样例TLE33,想了想,可能是完全连通图会让dfs非常耗时。
    看了tutorial结果还真是旅行商……

旅行商问题:
bool dp[i][j]=true 表示 i状态 且 下一步从第j个点走出去 的状态是有效的,false则无效
初始化dp[1<<i][i]=true 列表只有一首歌

  • 注意dp初始化
  • 因为频繁比较,对string要先哈希一下,数据小可以map/按照排序后下标来映射
posted @ 2025-02-03 22:12  Gusare  阅读(23)  评论(0)    收藏  举报