9.15
9.15
(1)div——约数贡献
真的是那天傻掉,,,
好像想出了正解,,,
反正挺简单
就是把A的每个数约数小于n的存下来,然后sort一下统计。。。
#include <queue>
#include <cmath>
#include <cstdio>
#include <vector>
#include <cstring>
#include <utility>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e7+5;
inline int read() {
int x=0;char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x;
}
int n,m;
int st[N],a,ans[205],top;
int main() {
n=read();m=read();
for(int i=1,j;i<=m;i++) {
a=read();
j=1;
for(j=1;j*j<a&&j<=n;j++)
if(a%j==0) {
st[++top]=j;
if(a/j<=n) st[++top]=a/j;
}
if(j*j==a) st[++top]=j;
}
sort(st+1,st+1+top);
int len=1;
for(int i=2;i<=top+1;i++) {
if(st[i]==st[i-1]) len++;
else ans[len]++,len=1;
}
ans[0]=n;
for(int i=1;i<=m;i++)
ans[0]-=ans[i];
for(int i=0;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}
(2)Market——另类背包
给定\(n\)个物品,每个物品可以不选或选一个,第\(i\)个物品的价格为\(c_i\),价值为\(v_i\),出现时间为\(t_i\)。有\(m\)个询问,每次询问在出现时间不超过\(T_i\)的所有物品中选若干件,总花费不超过\(M_i\)的情况下,被选择物品的价值和的最大值是多少。\(n≤ 300,m≤ 100000,ci,Mi ≤ 10^9,vi ≤ 300\)
我当时只会傻哈哈01dp,搞到50分
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=305;
inline int read() {
int x=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x;
}
inline void Max(int &x,int y){if(x<y)x=y;}
int n,m;
struct node{
int c,v,t;
bool operator < (const node &x) const {
return t==x.t?v>x.v:t<x.t;
}
}p[N];
int f[100005];
int main() {
n=read();m=read();
for(int i=1;i<=n;i++)
p[i].c=read(),p[i].v=read(),p[i].t=read();
sort(p+1,p+1+n);
int T,M,ans=0;
while(m--) {
T=read();M=read();ans=0;
for(int i=1;i<=n;i++) {
if(p[i].t>T) break;
for(int j=M;j>=p[i].c;j--)
Max(f[j],f[j-p[i].c]+p[i].v);
}
for(int i=0;i<=M;i++)
Max(ans,f[i]),f[i]=0;
printf("%d\n",ans);
}
return 0;
}
正解:
先将物品时间升序排列,离线询问,即可去掉时间的限制。
01背包,\(c\)和\(M\)太大无法承受。
考虑到\(v_i\)很小:记\(f[j]\)为选出\(j\)的价值和的最小花费
对于一个询问的答案就是:
1、算出在\(T_i\)时间内所能购买的物品范围\([1,x]\)
2、二分答案满足\(f[j]≤M_i\)的最大\(j\)
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m;
int f[90010],sum[305];
struct node{
int c,v,t;
}e[305];
int ans[100005];
struct Node{
int m,id;
bool operator < (const Node &a) const{
return m>a.m;
}
};
vector<Node> s[305];
bool cmp(node a,node b){
return a.t<b.t;
}
int read(){
int f=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
f=f*10+ch-'0';
ch=getchar();
}
return f*w;
}
signed main(){
n=read(),m=read();
for(int i=1;i<=n;i++){
e[i].c=read(),e[i].v=read(),e[i].t=read();
}
sort(e+1,e+1+n,cmp);
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+e[i].v;
}
for(int i=1;i<=m;i++){
int x=read(),y=read();
int hd=1,tl=n,mid,pos;
while(hd<=tl){
mid=(hd+tl)/2;
if(x>=e[mid].t){
pos=mid;
hd=mid+1;
}
else tl=mid-1;
}
if(x>=e[1].t&&x<=e[n].t) s[pos].push_back((Node){y,i});
else if(x>e[n].t) s[n].push_back((Node){y,i});
else ans[i]=0;
}
memset(f,0x3f,sizeof(f));
f[0]=0;
for(int i=1;i<=n;i++){
for(int j=sum[i];j>=e[i].v;j--){
f[j]=min(f[j],f[j-e[i].v]+e[i].c);
}
if(s[i].size()>0){//保证单调
sort(s[i].begin(),s[i].end());
int last=sum[i];
for(int j=0;j<s[i].size();j++){
for(int k=last;k>=0;k--){
if(f[k]<=s[i][j].m){
last=k;
ans[s[i][j].id]=k;
break;
}
}
}
}
}
for(int i=1;i<=m;i++)
cout<<ans[i]<<endl;
return 0;
}
孤岛营救问题
这个和上面那个十分类似,这里用bfs实现
#include <queue>
#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
inline int read() {
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return f*x;
}
const int N=12;
const int dx[]={1,-1,0,0},dy[]={0,0,1,-1};
int n,m,e[N][N][N][N],cnt[N][N],key[N][N][N];
bool vis[N][N][1<<14];
struct node {
int x,y,k,d;
node(){}
node(int _x,int _y,int _k,int _d) {
x=_x,y=_y,k=_k,d=_d;
}
};
int getkey(int x,int y) {
int ans=0;
for(int i=1;i<=cnt[x][y];++i) ans|=(1<<(key[x][y][i]-1));
return ans;
}
queue <node> q;
int bfs(int sx,int sy) {
int sk=getkey(sx,sy);
q.push(node(sx,sy,sk,0)),vis[sx][sy][sk]=1;
while(!q.empty()) {
node u=q.front(); q.pop();
if(u.x==n&&u.y==m) return u.d;
int ux=u.x,uy=u.y;
for(int i=0;i<4;++i) {
int vx=ux+dx[i],vy=uy+dy[i],opt=e[ux][uy][vx][vy];
if(vx<1||vx>n||vy<1||vy>m||opt<0||(opt&&!(u.k&(1<<(opt-1))))) continue;
int nxt=u.k|getkey(vx,vy);
if(vis[vx][vy][nxt]) continue;
q.push(node(vx,vy,nxt,u.d+1)),vis[vx][vy][nxt]=1;
}
}
return -1;
}
int main() {
int k,s,p;
n=read();m=read();p=read();k=read();
for(int i=1;i<=k;i++) {
int x1=read(),y1=read(),x2=read(),y2=read();
int g=read();
if(g) e[x1][y1][x2][y2]=e[x2][y2][x1][y1]=g;
else e[x1][y1][x2][y2]=e[x2][y2][x1][y1]=-1;
}
s=read();
for(int i=1;i<=s;i++) {
int x=read(),y=read(),g=read();
key[x][y][++cnt[x][y]]=g;
}
printf("%d\n",bfs(1,1));
return 0;
}