集训队日常训练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< ...
随机推荐
- 对XP上的KiFastSystemCall进行浅析
Windows API的系统调用过程通过KiFastSystemCall或int 2e进入内核,本文仅对XP上的KiFastSystemCall进行浅析. 以ntdll!ZwCreateProcess ...
- Android基础控件TextView
1.常用属性 <TextView android:id="@+id/text11" //组件id android:layout_width="match_paren ...
- 模板——AC自动机
传送门:QAQQAQ 定义nxt[u]=v表示从u开始不断沿着失配边跳到的第一个是标记点的端点v,那么我们再匹配时沿着last跳,每跳到一个last,它就一定对应一个模式串,所以效率是非常高的. 和K ...
- springmvc前端控制器拦截路径的配置报错404
1.拦截"/",可以实现现在很流行的REST风格.很多互联网类型的应用很喜欢这种风格的URL.为了实现REST风格,拦截除了jsp的所有. 2.拦截/*,拦截所有访问,会导致404 ...
- neo4j 实战、实例、示例 创建电影关系图 -1
1. 创建关系 因为代码占篇幅太大,创建整个"电源关系图"的代码在文章最下方. 2. 简单分析创建语句 2.1 创建电影节点 CREATE (TheMatrix:Movie {ti ...
- vue页面刷新数据丢失问题
参考: https://blog.csdn.net/aliven1/article/details/80743470 https://blog.csdn.net/liang37712 ...
- 订单风险系统BI
最近被公司叫去协助传统做维表查询服务,项目已经做完.和前端联调过程发现oracle对查询 sql和产品设计还是挺重要的.不能全部堆给代码去做,如何方便代码,代码优化到最高性能才是首要解决的事,前端才能 ...
- Create STKNetDiskC Instance Error
关于Create STKNetDiskC Instance Error错误的解决方法 这个错误可能出现在: AM8 附件直接存网盘的时候 报错 解决方法步骤如下: 在出现该错误的机器上,先将AM及 m ...
- 阿里云提供全托管 ZooKeeper
自 2010 年左右第一次引入以来,Apache ZooKeeper 目前在阿里巴巴集团内部已经有了将近 10 年的发展,使用的场景非常广泛,基于 ZooKeeper 强一致性的特点,被用在了分布式锁 ...
- C语言中结构体的深拷贝和浅拷贝
C++ 的浅拷贝和深拷贝(结构体) 拷贝有两种:深拷贝,浅拷贝 浅拷贝:拷贝过程中是按字节复制的,对于指针型成员变量只复制指针本身,而不复制指针所指向的目标 (1)结构体中不存在指针成员变量时 typ ...