集训队日常训练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< ...
随机推荐
- React中的Ajax
React中的Ajax 组件的数据来源,通常是通过Ajax请求从服务器获取,可以使用componentDidMount方法设置Ajax请求,等到请求成功,再用this.setState方法重新渲染UI ...
- C语言实现 计算个人所得税务2种方法
#include <stdio.h> #include <stdlib.h> /* 基于C语言的个人所得税计税系统 问题描述: 我国现行的个人所得税计算方法如下: 级数 全月应 ...
- IDEA中Git的使用(多人合作)
首先我们要简单知道github跟Git的区别.git是版本控制工具, github是一个面向开源及私有软件项目的托管平台,也是程序员交流的地方. 接下来就开始讲怎么多人一起开发. 首先我们先拥有git ...
- SpringBoot 05_集成SpringDataJpa
你还在为项目的集成头疼吗?你还在为管理大量的配置文件烦恼吗?如果是,用SpringBoot吧!今天主要介绍如果在SpringBoot的基础上创建一个集成了SpringDataJpa的项目,至于Spri ...
- 【LGP5112】FZOUTSY
题目 如果是\(hash\)做法的话显然就是把每一个位置后面的\(k\)个位置的hash值拿出来做一个莫队板子就好了 考虑一下牛逼的\(SAM\) 我们完全可以构造出来一棵后缀树,对于每个点找到其祖先 ...
- HtmlHelper2
一.隐式从ViewBag取数据 1.action中的代码: ViewBag.UserName = "admin"; cshtml中的代码: @Html.TextBox(" ...
- 11-3-while
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- elasticsearch 中文API 索引(三)
索引API 索引API允许开发者索引类型化的JSON文档到一个特定的索引,使其可以被搜索. 生成JSON文档 有几种不同的方式生成JSON文档 利用byte[]或者作为一个String手动生成 利用一 ...
- COCI2014/2015 Contest#1 D MAFIJA【基环树最大独立点集】
T1725 天黑请闭眼 Online Judge:COCI2014/2015 Contest#1 D MAFIJA(原题) Label:基环树,断环+树形Dp,贪心+拓扑 题目描述 最近天黑请闭眼在 ...
- vue 生产环境和测试环境的配置
我们引用的是axios 给src目录增加 api 文件夹 里面写上index.js // 配置API接口地址 var root = process.env.API_ROOT // 引用axios va ...