集训队日常训练20180518-DIV1
A.3583
n根木棍是否能分成相等两堆。
背包dp,首先求和sum,如果为偶数就说明不行,否则考虑做一个sum/2大小的背包。
#include<bits/stdc++.h>
using namespace std; int main()
{
int n,w[];
while(scanf("%d",&n)!=EOF)
{
int sum=;
for(int i=;i<=n;i++)scanf("%d",&w[i]),sum+=w[i];
bool dp[];
memset(dp,,sizeof dp);
dp[]=;
for(int i=;i<=n;i++)
for(int j=sum/;j>=w[i];j--)
dp[j]=dp[j]|dp[j-w[i]];
printf("%s\n",dp[sum/]&&sum%==?"Yes":"No");
}
return ;
}
A.cpp
B.5146
单身狗在[l,r]之间且二进制中1的数量最多的数,若有多个输出最小的。
贪心,可以发现想要二进制最多,那么一定从最低位开始。
那么想要在[l,r]之间,先把l变成二进制,贪心即可(想想为什么)。
#include<bits/stdc++.h>
using namespace std; #define ll __int64
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int a[]={},p=;
ll l,r,ans;
scanf("%I64d%I64d",&l,&r);
ans=l;
while(l)
{
a[p++]=l&;
l>>=;
}
for(int i=;i<=;i++)
{
if(a[i]==&&ans+(1LL<<i)<=r)
{
ans+=1LL<<i;
a[i]=;
}
}
printf("%I64d\n",ans);
}
return ;
}
B.cpp
C.3153
n个点m条无向边,问必须经过S<=10个点再回到起点0的最短路。
dijstra+状压dp,考虑对每个S跑一边dijstra,求出S到每个点的最短路。
dp[i][j]代表状态为i,现在在j点的最短路。
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=;
vector<pair<int,int> > G[N];
ll d[][N],dp[<<][];
int a[],T,n,m;
void dij(int p,int u)
{
for(int i=;i<n;i++)
d[p][i]=1LL<<;
d[p][u]=;
queue<int> qu;
qu.push(u);
while(!qu.empty())
{
int x=qu.front();
qu.pop();
for(int i=;i<G[x].size();i++)
{
int v=G[x][i].first,c=G[x][i].second;
if(d[p][v]>d[p][x]+c) d[p][v]=d[p][x]+c,qu.push(v);
}
}
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++) G[i].clear();
for(int i=,u,v,c;i<m;i++)
{
scanf("%d%d%d",&u,&v,&c);
G[u].push_back({v,c});
G[v].push_back({u,c});
}
scanf("%d",&m);
int S=<<m;
for(int i=;i<m;i++) scanf("%d",&a[i]),dij(i,a[i]);
for(int i=;i<S;i++)
for(int j=;j<m;j++)
dp[i][j]=1LL<<;
for(int i=;i<m;i++)
dp[<<i][i]=d[i][];
for(int s=;s<S;s++)
{
for(int i=;i<m;i++)
if((<<i)&s)
{
for(int j=;j<m;j++)
if(((<<j)&s)==)
dp[s|(<<j)][j]=min(dp[s|(<<j)][j],dp[s][i]+d[i][a[j]]);
}
}
ll ans=1LL<<;
for(int i=;i<m;i++)
ans=min(ans,dp[S-][i]+d[i][]);
printf("%I64d\n",ans);
}
return ;
}
C.cpp
D.3176
n<=30个值,每个值(0,2^16),求最小需要几个数的异或后值为0,每个数只能取1次。
背包dp,考虑dp[i]代表异或值为i的最少个数。
#include<bits/stdc++.h>
using namespace std; int main()
{
int n,x,dp[<<];
memset(dp,0x3f3f3f3f,sizeof dp);
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&x);
for(int j=(<<)-;j>=;j--)
dp[j^x]=min(dp[j^x],dp[j]+);
dp[x]=;
}
if(dp[]==0x3f3f3f3f)printf("-1");
else printf("%d",dp[]);
}
D.cpp
E.3166
给一堆等级,和每个等级的区间,然后n个初始得分,每小时加1分,每个查询输出D小时后达到等级L的人数。
二分,从小到大排序,那么就是有多少个数ai+D在等级L的区间内,就相当于区间-D,然后二分左右段点。
#include<bits/stdc++.h>
using namespace std; const int N=1e5+;
int a[N],n,q,d,l,L,R;
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
sort(a+,a++n);
scanf("%d",&q);
while(q--)
{
scanf("%d%d",&d,&l);
if(l==)L=,R=;
if(l==)L=,R=;
if(l==)L=,R=;
if(l==)L=,R=;
if(l==)L=,R=;
if(l==)L=,R=;
if(l==)L=,R=2e9+;
int x1=lower_bound(a+,a++n,L-d)-a;
int x2=upper_bound(a+,a++n,R-d)-a;
printf("%d\n",x2-x1);
}
return ;
}
E.cpp
F.2704
n个点m条无向边边权为1,从1出发问距离最远的点,如有多个输出编号最小的点,再输出距离,再输出有几个点。
dijstra模板题。
#include<bits/stdc++.h>
using namespace std; const int N=2e4+;
vector<int>G[N];
int n,m,u,v;
void bfs()
{
int d[N];
memset(d,0x3f3f3f3f,sizeof d);
queue<int>q;
d[]=;
q.push();
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=;i<G[u].size();i++)
{
int v=G[u][i];
if(d[v]>d[u]+)
{
d[v]=d[u]+;
q.push(v);
}
}
}
int maxx=-,posi=,ans=;
for(int i=;i<=n;i++)
if(d[i]>maxx)maxx=d[i],posi=i;
for(int i=;i<=n;i++)
if(d[i]==maxx)ans++;
cout<<posi<<" "<<maxx<<" "<<ans;
}
int main()
{
cin>>n>>m;
for(int i=;i<m;i++)
{
cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}
bfs();
return ;
}
F.cpp
G.3168
n瓶奶生产商和生产日期保证2008年,m个生产商对应奶的保质期,给你一个开始的日期,每天最多喝一瓶,问最少几瓶会过期。
哈希+贪心,把每个日期转化成天,优先处理过期时间最早的。
#include<bits/stdc++.h>
using namespace std;
int a[]={,,,,,,,,,,,,};
vector<int>v[];
int b[];
int main()
{
std::ios::sync_with_stdio(false);
map<string,int>m;
int id=,n,x,y;
char ch;
string s;
cin>>n;
for(int i=;i<=n;i++)
{
cin>>s;
if(m[s]==)
m[s]=id++;
cin>>x>>ch>>y;
int day=;
for(int j=;j<x;j++)
day+=a[j];
day+=y;
v[m[s]].push_back(day);
}
int t;
cin>>t;
for(int i=;i<=t;i++)
{
cin>>s>>x;
for(int j=;j<v[m[s]].size();j++)
b[v[m[s]][j]+x]++;
}
cin>>x>>ch>>y;
int day=;
for(int j=;j<x;j++)
day+=a[j];
day+=y;
int sum=;
for(int i=;i<=day;i++)
sum=sum+b[i];
int p=day;
for(int i=day+;i<;i++)
{
while(b[i]>)
{
if(p<i)
p++,b[i]--;
else
{
sum+=b[i];
break;
}
}
}
cout<<sum<<endl;
return ;
}
G.cpp
H.3213
n<=8个题目选择k个难度总和<=p求方案数。
n很小,直接暴力dfs。
#include <bits/stdc++.h>
using namespace std;
int v[],n,k,p,ans;
void DFS(int pos,int s,int cnt)
{
if(s <= p && cnt == k) {ans++;return;}
if(cnt > k || s > p) return;
for(int i = pos; i < n; i++)
{
DFS(i + ,s + v[i],cnt + );
}
}
int main()
{
int t; scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&k,&p);
for(int i = ; i < n; i++) scanf("%d",&v[i]);
ans = ;
DFS(,,);
printf("%d\n",ans);
}
return ;
}
H.cpp
I.5069
给n*m的图,求一个四周全是‘.’的最大矩形。
思维,a为列前缀和,b为行前缀和,(i,j)---(i,k)那么第i行的a[i][k]-a[i][j]==k-j那么第i行j->k都是1,x=min(b[i][j],b[i][k])代表j向上或者k向上连续1的数量,然后只需要判断a[i-x+1][k]-a[i-x+1][j]==k-j,这就说明第i-x+1行j->k都是1,复杂度O(n^3)。
#include<bits/stdc++.h>
using namespace std; int n,m;
char G[][];
int a[][],b[][];
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%s",G[i]+);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(G[i][j]=='.')
a[i][j]=a[i][j-]+,
b[i][j]=b[i-][j]+;
else
a[i][j]=,
b[i][j]=;
//(i,j) (i,k)
int maxx=;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
for(int k=j;k<=m;k++)
{
if(a[i][k]-a[i][j]!=k-j)break;
if(b[i][j]&&b[i][k])
{
int x=min(b[i][j],b[i][k]);
while(a[i-x+][k]-a[i-x+][j]!=k-j)x--;
maxx=max(maxx,x*(k-j+));
}
}
}
printf("%d",maxx);
return ;
}
I.cpp
J.4482
n个数的积为A,m个数的积为B,求A和B的gcd。
zdragon的O((n+m)*sqrt(1e9))
求A的所有素因子,求B的所有素因子,枚举所有素因子,答案就是素因子^(该素因子A有几个,该素因子B有几个)的积。
#include <bits/stdc++.h>
using namespace std;
const int N=;
const int MD=;
int a[N<<],b[N<<],cnt;
bool f;
map<int,int> ma,mma;
long long quick_pow(long long x,int y)
{
long long ans=;
while(y)
{
if(y&)
{
ans*=x;
if(ans>MD||f) ans%=MD,f=true;
}
x*=x;
if(x>MD||f) x%=MD,f=true;
y>>=;
}
return ans;
}
int main()
{
int n,m;
scanf("%d",&n);
for(int i=,x;i<n;i++)
{
scanf("%d",&x);
for(int j=;1LL*j*j<=x;j++)
{
if(x%j==)
{
if(!ma[j]) ma[j]=(++cnt),mma[cnt]=j;
while(x%j==) a[ma[j]]++,x/=j;
}
}
if(x>)
{
if(!ma[x]) ma[x]=(++cnt),mma[cnt]=x;
a[ma[x]]++;
}
}
scanf("%d",&m);
for(int i=,x;i<m;i++)
{
scanf("%d",&x);
for(int j=;1LL*j*j<=x;j++)
{
if(x%j==)
{
if(!ma[j]) ma[j]=(++cnt),mma[cnt]=j;
while(x%j==) b[ma[j]]++,x/=j;
}
}
if(x>)
{
if(!ma[x]) ma[x]=(++cnt),mma[cnt]=x;
b[ma[x]]++;
}
}
long long ans=;
for(int i=;i<=cnt;i++)
{
ans=ans*quick_pow(1LL*mma[i],min(a[i],b[i]));
if(ans>MD||f) ans%=MD,f=true;
}
if(f) printf("%09I64d\n",ans);
else printf("%I64d\n",ans);
return ;
}
J.cpp O((n+m)*sqrt(1e9))
wff的O(n*m)
暴力gcd。
#include <bits/stdc++.h>
using namespace std;
const int inf =0x3f3f3f3f;
#define ll long long int a[],b[];
int main()
{
ll ans1=,ans2=;
int n,m;
scanf("%d",&n);
for(int i=;i<n;i++)
{
scanf("%d",&a[i]);
}
scanf("%d",&m);
for(int i=;i<m;i++)
{
scanf("%d",&b[i]);
}
int flag=;
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
int t=__gcd(a[i],b[j]);
ans1=1ll *ans1 * t ;
if(!flag&&ans1>= ) flag=;
ans1%=;
a[i]/=t;
b[j]/=t;
}
}
if(flag) printf("%09I64d",ans1% );
else printf("%I64d",ans1% );
return ;
}
J.cpp O(n*m)
K.4426
n个人初始分ai,第一名+n分,第二名+n-1分,以此类推,如果一个人i是冠军那么他的得分大于等于其他所有人的得分,问有几个人可能是冠军。
贪心,首先按ai从小到大排序,得分最高的加1分,第二高加2分,以此类推,maxx=ai+n-i+1的最大值,如果一个人i是冠军,那么ai+n大于等于maxx。
#include<bits/stdc++.h>
using namespace std; const int N=3e5+;
int a[N],n,ans,sum;
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
sort(a+,a++n);
for(int i=n;i>=;i--)ans=max(ans,a[i]+n-i+);
for(int i=;i<=n;i++)if(a[i]+n>=ans)sum++;
printf("%d",sum);
return ;
}
K.cpp
L.3457
给一个整数,输出重排列后的最小值。
贪心,首先第一个数不能为0,那么先取个不是0的最小放在第一个。然后按小到大输出。
#include<stdio.h>
#include<string.h>
int main()
{
int i,j;
char a[];
while(scanf("%s",&a)!=EOF)
{
int b[]={},min=;
for(i=;i<strlen(a);i++)
{
b[a[i]-'']++;
if(a[i]-''<min&&a[i]-''!=)
min=a[i]-'';
}
printf("%d",min);
b[min]--;
for(i=;i<;i++)
{
for(j=;j<b[i];j++)
printf("%d",i);
}
printf("\n");
}
return ;
}
L.cpp
M.2609
n个点m条无向边最多k次操作使得边花费为0,求1到n的最短路。
堆优化的dijstra+dp,分成k层,dp[k][i]表示已经让k条边花费变成0到i的最短路。
#include<bits/stdc++.h>
using namespace std; const int maxn=1e4+;
const int maxm=5e4+;
const int maxk=+; inline int read() {
int x=,f=;char c=getchar();
for(;c<''||''<c;c=getchar())if(c=='-')f=-;
for(;''<=c&&c<='';c=getchar())x=(x<<)+(x<<)+c-'';
return x*f;
} vector< pair<int,int> >G[maxn];
int d[maxk][maxn],vis[maxk][maxn];
int n,m,k;
struct edge
{
int v,k,w;
bool operator<(const edge& D)const{
return w>D.w;
}
};
int dij()
{
for(int i=;i<=k;i++)for(int j=;j<=n;j++)d[i][j]=0x3f3f3f3f,vis[i][j]=;
priority_queue<edge>q;
q.push({,,});
d[][]=;
while(!q.empty())
{
edge u=q.top();q.pop();
//printf("%d %d\n",u.v,u.w);
if(u.v==n)return u.w;
if(vis[u.k][u.v])continue;
vis[u.k][u.v]=;
for(auto x:G[u.v])
{
int v=x.first;
int w=x.second;
if(d[u.k][v]>u.w+w)
q.push({v,u.k,d[u.k][v]=u.w+w});
if(u.k<k&&d[u.k+][v]>u.w)
q.push({v,u.k+,d[u.k+][v]=u.w});
}
}
return 0x3f3f3f3f;
}
int main()
{
n=read(),m=read(),k=read();
for(int i=,u,v,w;i<=m;i++)
{
u=read(),v=read(),w=read();
G[u].push_back({v,w});
G[v].push_back({u,w});
}
printf("%d\n",dij());
return ;
}
M.cpp
集训队日常训练20180518-DIV1的更多相关文章
- 集训队日常训练20181117 DIV2
大佬们一顿操作猛如虎,拼命AC强啊 4262: 区间异或 Time Limit(Common/Java):1000MS/3000MS Memory Limit:65536KByteTotal ...
- 集训队日常训练20181201 C 1003 : 种类数
时间限制(普通/Java):2000MS/6000MS 内存限制:65536KByte总提交: 8 测试通过:5 描述 一共有 n个数,第 i 个数是 xi ,其中xi ...
- 集训队日常训练20181201 E 1005 : 小蝌蚪
时间限制(普通/Java):500MS/1500MS 内存限制:65536KByte总提交: 25 测试通过:5 描述 有 n 个装着小蝌蚪的水缸排成一排,你拥有一个无限 ...
- 集训队日常训练20181124 DIV2
急急忙忙要出去比赛就拉了一场有点sb的题目 5202: 网络寻路 时间限制(普通/Java):1000MS/3000MS 内存限制:65536KByte总提交: 15 ...
- 集训队日常训练20181110 DIV2 题解及AC代码
4375: 孪生素数 Time Limit(Common/Java):1000MS/3000MS Memory Limit:65536KByteTotal Submit: 324 ...
- 集训队日常训练20180525-DIV2
A.2295 求有多少素数对和等于n. 暴力. #include <bits/stdc++.h> using namespace std; int ss(int n) { ,a=sqrt( ...
- 集训队日常训练20180525-DIV1
A.2805 N*M的图,每次浇水(X1,Y1)-(X2,Y2)围成的矩形,问最后有多少点被浇水了. 暴力. #include<bits/stdc++.h> using namespace ...
- 集训队日常训练20180518-DIV2
A.3232 n个物品,换取要花积分,问刚好花完积分能换最大多少价值的物品. 多重背包. #include <bits/stdc++.h> using namespace std; ]; ...
- 集训队日常训练20180513-DIV1
A.3132 给一个有向图,问能否从任意点出发都能进入一个环中. 深搜. #include<bits/stdc++.h> using namespace std; ; vector< ...
随机推荐
- MyEclipse使用总结——将原有的MyEclipse中的项目转成maven项目[转]
前面一篇文章中我们了解了 在myeclipse中新建Maven框架的web项目 那么如果我们原来有一些项目现在想转成maven项目应该怎么做呢 我收集到了三种思路: 一.新建一个maven项目,把原项 ...
- iOS开发CGImage.h简介
1.前因 由于剪切图片用到下面方法,此方法属于CGImage.h中,通过创建CGImageRef像素位图,可以通过操作存储的像素位来编辑图片. /* Create an image using the ...
- ubuntu关闭防火墙(默认命令)
- Netty TCP粘包/拆包问题《一》
1.使用LineBasedFrameDecoder,StringDecoder解析器进行解决TCP粘包/拆包问题 2.代码搞起: TimeClient:客户端 /* * Copyright 2013- ...
- Android 开发 DNK开发将.c文件打包成os
前言 不废话太多,Java与C之间联系的JNI的概念,这个要了解可以参考下面这个博客: https://www.jianshu.com/p/87ce6f565d37 此博客只说明如何将.C文件通过ND ...
- ubuntu 安装samba共享文件夹
安装samba sudo apt-get install samba smbclient 配置samba sudo cp /etc/samba/smb.conf /etc/samba/smb.conf ...
- [转]WPF中Binding的技巧
在WPF应用的开发过程中Binding是一个非常重要的部分. 在实际开发过程中Binding的不同种写法达到的效果相同但事实是存在很大区别的. 这里将实际中碰到过的问题做下汇总记录和理解. 1. so ...
- iotop实时监控磁盘io
介绍 Linux下的IO统计工具如iostat, nmon等大多数是只能统计到per设备的读写情况, 如果你想知道每个进程是如何使用IO的就比较麻烦. iotop 是一个用来监视磁盘 I/O 使用状况 ...
- 廖雪峰Java10加密与安全-4加密算法-2口令加密算法
对称加密key是一个byte数组,如AES256算法的key是一个32字节的数组,普通的加密软件由用户输入加密口令.如果由用户输入口令,进行加密/解密,需要用到PBE算法. 1.PBE:Passwor ...
- bzoj1003物流运输 最短路+DP
bzoj1003物流运输 题目描述 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的运输路线,以便对整个运输 ...