题意:计算n次A+B。
思路:模拟即可。
代码:
#include
using namespace std;
typedef long long ll;
int main()
{
int n;
cin>>n;
while(n--){
ll a,b;
cin>>a>>b;
cout<
题意:对n个字符串的前k个字符串,按照字典序输出(这个题很容易理解错误题意,以为是对n个排序)。
思路:对前k个字符串排序并输出。
代码:
#include
using namespace std;
typedef long long ll;
int main()
{
int n,k;
cin>>n>>k;
string s[n+5];
for(int i=0;i>s[i];
sort(s,s+k);
for(int i=0;i
题意:给定一个无向图,问最少删除几条边可以使图中不成环。
思路:并查集板子
代码:
#include
using namespace std;
typedef long long ll;
typedef struct bcj{
vectorv,siz,mn,mx;
bcj(int n):v(n),siz(n,1){
std::iota(v.begin(),v.end(),0),mn=mx=v;
}
int leader(int x){
while(x!=v[x])
x=v[x]=v[v[x]];
return x;
}
bool same(int a,int b) {
return leader(a)==leader(b);
}
bool merge(int a,int b) {
a=leader(a);
b=leader(b);
if(a==b)
return false;
siz[a]+=siz[b];
mn[a]=std::min(mn[a],mn[b]);
mx[a]=std::max(mx[a],mx[b]);
v[b]=a;
return true;
}
int size(int a){
return siz[leader(a)];
}
int min(int a){
return mn[leader(a)];
}
int max(int a) {
return mx[leader(a)];
}
}bcj;
int main() {
int n,m;
cin>>n>>m;
bcj b(n+1);
int ans=0,u,v;
for(int i=0;i>u>>v;
if(!b.merge(u,v)) ans++;
}
cout<
题意:
在n个数中找到[l,r]之间的数,以k为一组同时对这个区间的数加上一个数c,看能不能将[l,r]之间的数都变为0
思路:
对于[l,r]之间的数,判断下标i %k之后的的k个前缀和是否相同,
直接判断会时间超限,要用数组求前缀和进行优化,通过区间前缀和的差进行求取。
代码:
#include
using namespace std;
typedef long long ll;
int main()
{
int n,k;
cin>>n>>k;
vector a(n);
vector sum(n);
for(int i=0;i>a[i];
sum[i]=a[i];
if(i>=k) sum[i]+=sum[i-k];
}
int q;
cin>>q;
while(q--){
int l,r;
cin>>l>>r;
l--,r--;
vector b(k);
int flag=1;
for(int i=r;r-i+1<=k;i--)
b[i%k]+=sum[i];
for(int i=l-1;i>=0&&l-i<=k;i--)
b[i%k]-=sum[i];
for(int i=1;i
题意:
给出n个物品,每个物品有一个日常价格Ai。有m个想要的物品,分别为Xi。
重复以下操作:剩余的物品数量为r,可以在1-r中任选一个数j,购买日常价格第j小的物品,同时价值附加Cj,找出能够买到m个想要物品的最小价值。
思路:
采用dp的思想。
对于一个物品,它的最小购买价值为 它的日常价值+在剩余未被购买的物品中第几小的价值。
dp[i] 第 i 个被选的最小花费,枚举第几个被选到, 对于第 i 个物品只可能用到c[0, i - 1]
分为n次进行,每次用g[]表示,结束后重新更新dp
cost = min(cost, c[i - j]);
g[j+1]=min(g[j+1],dp[j]+a[i]+cost)
同时,如果不是必须物品,也可以不选
代码:
#include
using namespace std;
typedef long long ll;
const ll INF = 2E18;
int main()
{
int n, m;
cin>>n>>m;
vector a(n),c(n),must(n);
for(int i=0;i>a[i];
for(int i=0;i>c[i];
for(int i=0;i>x;
x--;
must[x]=1;
}
vector dp(n + 1, INF);
// dp[i] 第 i 个被选的最小花费 -> dp[i][j] 第 i 个物品, 第 j 个被选的最小花费
dp[0] = 0;
for(int i=0;i g(n+1,INF);
int cost=1E9;
for(int j=0;j<=i;j++){ // 枚举第几个被选到, 对于第 i 个物品只可能用到c[0, i - 1]
cost = min(cost, c[i - j]); // 前面被选的个数越多, i 可能往前的位置越多, 选择更多
g[j+1]=min(g[j+1],dp[j]+a[i]+cost);
if(!must[i]){ // 非必选 可以不选
g[j]=min(g[j],dp[j]);
}
}
swap(g,dp);
}
cout<<*min_element(dp.begin(), dp.end());
return 0;
}
题意:
一个数有n位,将1-n-1位分为不同的集合,每个集合中的数与相乘,再与最后剩下的数相乘,求所有分类方法乘积的和
思路:
采用dp的思想。
X[j : i]=10X[j : i−1]+X[i : i],定义X[i : i−1]=0
当i>2时,
代码:
#include
using namespace std;
typedef long long ll;
const int mod=998244353;
int main()
{
int n;
cin>>n;
string s;
cin>>s;
vector dp(n+1),f(n+1);
dp[0]=0,f[0]=1;
for(int i=0;i
题意:
N维扫雷问题,已知每个位置上相邻位置炸弹的总数,求每个位置上的炸弹数
思路:
找到在同一维度上的3个点,假设这三个点依次为a b,c,对应位置为0 1 2,
得到每个位置的值w0,w1,w2,那么位置0的雷数为w1-w2,位置2的雷数为w1-w0,位置0的雷数为w1-位置0的雷数-位置2的雷数,
代码:
#include
using namespace std;
typedef long long ll;
int n;
ll pw[20],a[(int)pow(3,12)+5];
int main()
{
cin>>n;
pw[0]=1;
for(int i=1;i<=n;i++) pw[i]=pw[i-1]*3;
for(int i=0;i>a[i];
for(int b=0;b