• 【2019.10.25】


    summary

    • 分情况拿分保底真的很好用 像我这种辣鸡应该注意保底
    • 打题不要慌 有条理 不要东一条西一条

    小奇采药

    对于 30% 的数据,O(2n ) 枚举取 or 不取

    对于 60% 的数据,O(nm) 做 01 背包,即 f(i, j) 表示前 i 株 草药,耗费 j 的时间能达到的最⼤代价。

    对于 100% 的数据,注意到 m,t,v 纯随机

    那么不会选太多的草药,⽽耗时较少的草药有很⼤概率存在 于最优解中

    针对这些性质优化搜索

    当然也可以合理使用随机化和卡时,复杂度 O(⽞学)

    最基础60昏的背包

    dfs写错了... 幸好我分开搞得 不然就爆炸

    struct node{int co,val;}a[N];
    bool cmp(node x,node y){return x.co>y.co;}
    
    ll f[100010],ans,sumc[N],sumv[N];
    void work(){//60昏 
    	memset(f,0,sizeof(f));
    	for(int i=1;i<=n;++i)
    	for(int j=m;j>=a[i].co;--j)
    	f[j]=max(f[j],f[j-a[i].co]+a[i].val);
    	printf("%lld
    ",f[m]);
    }
    
    bool vis[N];
    void dfs(int pos,ll co,ll val){
    	ans=Max(ans,val);
    	if(pos>n) return;
    	if(co+a[n].co>m) return;
    	if(val+sumv[pos]<=ans) return;
    	if(co+sumc[pos]<=m){ans=Max(val+sumv[pos],ans);return;}
    	if(co+a[pos].co<=m) dfs(pos+1,co+a[pos].co,val+a[pos].val);
    	dfs(pos+1,co,val);
    }
    void work2(){
    	ans=0;dfs(1,0,0);
    	printf("%lld
    ",ans);
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
    	int T;rd(T);
    	while(T--){
    		rd(n),rd(m),sumv[n+1]=sumc[n+1]=0;
    		for(int i=1;i<=n;++i) rd(a[i].co),rd(a[i].val);
    		sort(a+1,a+n+1,cmp);
    		for(int i=n;i;--i) sumv[i]=sumv[i+1]+a[i].val,sumc[i]=sumc[i+1]+a[i].co;
    		//if(m<=100000) work();
    		work2();
    	}
    	return 0;
    }
    

    小奇的数列2

    第一反应 双指针?!

    很容易发现 若一个区间为可约的 那么这个区间的gcd一定等于其最小值

    然后发现可以二分 就开始打线段树来维护 打完后发现二分的过程中有很多此询问 gcd和最小值都可以用st表来维护 然后(O(1))询问最合适了!

    然后这就是正解辽?!

    int gcd(int x,int y){return !y?x:gcd(y,x%y);}
    int gc,mn;
    void query(int x,int y){
    	int s=lg[y-x+1];
    	gc=gcd(Gc[x][s],Gc[y-(1<<s)+1][s]),mn=Min(Mn[x][s],Mn[y-(1<<s)+1][s]);
    }
    bool check(int mid){
    	for(int l=1;l+mid<=n;++l)
    	if(query(l,l+mid),gc==mn) return 1;
    	return 0;
    }
    int main(){
    	//freopen("sequence.in","r",stdin);
    //	freopen("sequence.out","w",stdout);
    	rd(n);
    	for(int i=1;i<=n;++i) rd(a[i]);
    	cm[0]=1,lg[0]=-1;for(int i=1;i<20;++i) cm[i]=cm[i-1]<<1;
    	for(int i=1;i<=n;++i) Gc[i][0]=Mn[i][0]=a[i],lg[i]=lg[i>>1]+1;Mn[n+1][0]=0;
    	for(int j=1;j<20;++j)
    		for(int i=1;i+cm[j]-1<=n+1;++i){
    			Gc[i][j]=((Gc[i][j-1]==1||Gc[i+cm[j-1]][j-1]==1)?1:gcd(Gc[i][j-1],Gc[i+cm[j-1]][j-1])),
    			Mn[i][j]=Min(Mn[i][j-1],Mn[i+cm[j-1]][j-1]);
    		}
    	int l=0,r=n-1,mid,ans,cnt=0;
    	while(l<=r){
    		int mid=l+r>>1;
    		if(check(mid)) l=mid+1,ans=mid;
    		else r=mid-1;
    	}
    	if(!ans){
    		printf("%d %d
    ",n,0);
    		for(int i=1;i<=n;++i) printf("%d ",i);
    	}
    	else{
    		for(int i=1;i+ans<=n;++i)
    			if(query(i,i+ans),gc==mn) b[++cnt]=i;
    		printf("%d %d
    ",cnt,ans);
    		for(int i=1;i<=cnt;++i)  printf("%d ",b[i]);
    	}
    	return 0;
    }
    

    小奇学数论

    我... 表打炸了...

    对于 20% 的数据,枚举 1 到 n,暴⼒判断素数。

    对于 40% 的数据,枚举 1 到 n,判断素数的时候只需要循 环 1 − √ n

    对于 60% 的数据,筛法

    对于 80% 的数据,容斥原理

    对于 100% 的数据,分段 + 前缀和打表 还有个⿊科技 Meissel-Lehmer 算法

    分块打表 打表时用的是做素数密度那道题的方法==

    int cnt=0,prime[700000];bool v[N];
    void primes(){
    	for(ll i=2;i<=n;++i){
    		if(!v[i]) v[i]=1,prime[++cnt]=i;
    		for(int j=1;j<=cnt&&i*prime[j]<=n;++j){
    			v[i*prime[j]]=1;
    			if(!(i%prime[j])) break;
    		}
    	}
    }
    
    bool a[5000010];
    void work(){
    	m=n,n=1000000ll;primes();
    	for(int i=1;i<=m/5000000;++i) ans+=table[i];
       	ll L=(m/5000000ll+1)*5000000ll,R=m;
       	if(!(m%5000000ll)) {printf("%lld
    ",ans);return;}
        memset(a, 0, sizeof(a));
        for (int i=1;i<=cnt;++i)
            for(ll j=max(2ll,(L-1)/prime[i]+1)*prime[i];j<=R;j+=prime[i]) a[j-L]=1;
        for(ll i=L;i<=R;++i)
        	if(!a[i - L]) ++ans;
        printf("%lld",ans);
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
    	rd(n);
    	if(n<=10000000){
    		primes();
    		printf("%d",cnt);
    	}
    	else work();
    /*	int i=1;
    	for(;i<=20000;++i) if(table[i]==2) break;
    	printf("%d",i);*/
    	return 0;
    }
    
  • 相关阅读:
    jQuery 重新温习 遗忘知识点
    正则表达式获取博客园随笔1
    用django创建一个简单的sns
    WCF小实例以及三种宿主
    iOS: imageIO完成渐进加载图片
    Excel 菜单系统
    分布式EventBus的Socket实现
    Jenkins安装plugin
    邮件系统存储设计问答
    在Windows上使用CodeLite+MinGW+Clang进行开发
  • 原文地址:https://www.cnblogs.com/lxyyyy/p/11738487.html
Copyright © 2020-2023  润新知