A - Large Digits
给2个数 求出他们每一位的和比较大小并输出
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+10;
int main(){
string a,b;
cin>>a>>b;
int ans1=0,ans2=0;
for(int i=0;i<a.size();i++){
ans1+=a[i]-'0';
}
for(int i=0;i<b.size();i++){
ans2+=b[i]-'0';
}
printf("%d",max(ans1,ans2));
return 0;
}
B - Gentle Pairs
给出n个坐标
求出能形成的直线斜率在-1到1之间的数量
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+10;
int x[N],y[N];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(1.0*(y[i]-y[j])/(x[i]-x[j])<=1&&1.0*(y[i]-y[j])/(x[i]-x[j])>=-1)ans++;
}
}
cout<<ans;
}
C - 1-SAT
题意:如果!+字符出现过2次是不安全的
入门不存在这样的 那么输出"satisfiable“
#include<iostream>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
const int N=2e5+10;
map<string,int>mp;
int main(){
int n;
scanf("%d",&n);
string a;
bool flag=0;
string ans;
for(int i=1;i<=n;i++){
cin>>a;
if(a[0]=='!'){
if(mp.count(a.substr(1,a.size()-1))){
flag=1;
ans=a.substr(1,a.size()-1);
}
mp[a]=1;
}
else{
if(mp.count("!"+a)){
flag=1;
ans=a;
}
mp[a]=1;
}
}
if(flag){
cout<<ans;
}
else cout<<"satisfiable";
}
D - Choose M
题意:高桥选择一个地方会得到a+b个支持者 另一个人得到所有的没被选的a
高桥不选择的话不会得到任何东西
问高桥最少选择多少个地方使得支持者大于另外一个人
思路:排序贪心即可
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=5e5+10;
typedef long long LL;
LL a[N];
bool cmp(LL x,LL y){
return x>y;
}
int main(){
int n;
scanf("%d",&n);
LL sum=0;
for(int i=1;i<=n;i++){
int x,y;
scanf("%d%d",&x,&y);
sum-=x;
a[i]=2*x+y;
}
sort(a+1,a+1+n,cmp);
LL ans=0;
for(int i=1;i<=n;i++){
sum+=a[i];
if(sum>0){
printf("%d\n",i);
return 0;
}
}
}
E - Through Path
思路:树形dp(树上差分) 首先我们以1为根节点 遍历所有节点
并将所有的确立自己的父亲
如果选择a b点中的a点
如果b是a的父亲 那么就是a的所有子树都要增加x 直接在ans[a]上增加
如果b不是a的父亲 那么说b是a的儿子 b上的所有子树都不能增加 而除了b和b的子树都要加 这里就是树上差分了 根节点+x (ans[1]+=x)而子树b全部要减去x(ans[b]-=x)
处理完所有询问后直接一边dfs 所有儿子的ans[u]加上ans[father]即可
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=2e5+10;
struct Edge{
int v,next;
}edge[N<<1];
int head[N],tot,p[N],a[N],b[N];
LL ans[N];
void add(int u,int v){
edge[++tot]={
v,head[u]};
head[u]=tot;
}
void dfs(int u,int father){
ans[u]+=ans[father];
p[u]=father;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].v;
if(v!=father){
dfs(v,u);
}
}
}
int main(){
int n,q;
scanf("%d",&n);
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&a[i],&b[i]);
add(a[i],b[i]);
add(b[i],a[i]);
}
dfs(1,0);
scanf("%d",&q);
for(int i=1;i<=q;i++){
int t,e,x,u,v;
scanf("%d%d%d",&t,&e,&x);
u=a[e],v=b[e];
if(t==2){
swap(u,v);
}
if(p[u]==v)ans[u]+=x;
else ans[1]+=x,ans[v]-=x;
}
dfs(1,0);
for(int i=1;i<=n;i++)
printf("%lld\n",ans[i]);
}
F - Close Group
给出一个图差分成完全图
完全图数量最少是多少
点的数量只有18 这里我们思考二进制枚举 状态压缩dp
每一位表示选上这几个点 最少差分成几个完全图
check函数返回是否是完全图 如果是 返回1
最后枚举所有状态往后推 每个状态枚举自己的所有的差分子集取最小值
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=20;
int f[1<<N];
int G[N][N],n,m;
int check(int x){
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if((x>>(i-1))&1){
if((x>>(j-1))&1){
if(!G[i][j])return n;
}
}
}
}
return 1;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
G[u][v]=G[v][u]=1;
}
for(int i=1;i<(1<<n);i++){
f[i]=check(i);
}
for(int i=1;i<(1<<n);i++){
for(int s=i;s;s=i&(s-1)){
f[i]=min(f[i],f[i^s]+f[s]);
}
}
cout<<f[(1<<n)-1];
return 0;
}