集训队日常训练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< ...
随机推荐
- VUE环境下获取当前时间并格式化--按秒数更新
<el-col :span="8"><div class="grid-content title-time"> {{date}}< ...
- 使用async读取异步数据
使用传统方式读取异步数据 const fs = require('fs') fs.readFile('readme.txt', function (err, data) { console.log(d ...
- Spring Cloud Config-Client 无法获取 Config-Server 在 github 上的配置文件的属性值,竟然是因为
Spring Cloud Config-Client 无法获取 Config-Server 在 github 上的配置文件的属性值,竟然是因为!!! 2018年07月23日 16:33:25 一颗很菜 ...
- 新启vue_cli项目+引入Element
[1]安装vue_cli vue init webpack 项目名字 [2]安装Element-UI cnpm install element-ui -S //写入dependencies cnpm ...
- hive报错( Non-Partition column appears in the partition specification)
在写及测的过程中发现的,有一些可能需要进一步验证.有时候hive报错位置不一定正确需要多确认 1 FAILED: NullPointerException null 不能用视图作为left outer ...
- 跟我一起实战美团网一之[nodemon] app crashed - waiting for file changes before starting...
环境准备 第一步安装 npm install -g npx npx create-nuxt-app at-app 与事件相关的包我们再安装一次 npm install --update-binary ...
- Django项目:CRM(客户关系管理系统)--65--55PerfectCRM实现CRM客户报名状态颜色变化
# kingadmin.py # ————————04PerfectCRM实现King_admin注册功能———————— from crm import models #print("ki ...
- C#可扩展编程之MEF(三):导出类的方法和属性
前面说完了导入和导出的几种方法,如果大家细心的话会注意到前面我们导出的都是类,那么方法和属性能不能导出呢???答案是肯定的,下面就来说下MEF是如何导出方法和属性的. 还是前面的代码,第二篇中已经 ...
- MyISAM 与 innoDB 的选择
1.MyISAM:默认表类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法.不 ...
- PAT甲级——A1054 The Dominant Color
Behind the scenes in the computer's memory, color is always talked about as a series of 24 bits of i ...