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;
}

posted @ 2020-09-20 10:13  ke_xin  阅读(49)  评论(0编辑  收藏  举报