2021-10-30(每周总结)

142 篇文章 0 订阅
92 篇文章 0 订阅

这周学了点数学的东西,Java的大数类,快速幂,矩阵快速幂,近几天做的codeforce不大好,思路想不出来,又陆陆续续做了几个dp背包的题,感觉dp的练习还是差的很远啊,而且dp有很大一部分是与别的知识点一块出题,遍往下学边刷题吧

luogu p2979

第一种情况不考虑大奶酪

第二种情况是考虑大奶酪;因为存在大奶酪会压扁下面的奶酪,所以T最大是T*5/4

P2979 [USACO10JAN]奶酪塔Cheese Towers - Cxs3 - 洛谷博客 (luogu.com.cn)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#include<ctime>
#define ll long long
#define CHECK(x,y) (x>0&&x<=n&&y>0&&y<=m)
const int inf=0x3f3f3f3f;
const int mod=1e9;
const int N=1e6+5;
using namespace std;
int n,t,k,v[110],h[110];
ll f[2000];
int main(){
   //freopen("in.txt","r",stdin);
    scanf("%d%d%d",&n,&t,&k);
    for(int i=1;i<=n;i++) scanf("%d%d",&v[i],&h[i]);
    memset(f,0,sizeof(f));
    for(int i=1;i<=n;i++){
        for(int j=h[i];j<=t*5/4;j++)
            f[j]=max(f[j],f[j-h[i]]+v[i]);
    }
    ll ans=f[t];
    for(int i=1;i<=n;i++)
        if(h[i]>=k) ans=max(ans,f[(t-h[i])*5/4]+v[i]);
    cout<<ans<<endl;
    return 0;
}

luogu p5365

一个多重背包题,懵逼的我看了题解才知道。。。钱作为容量,方案数为价值;dp[j]代表钱为j时能获得的最大方案数,容量qb就等于所有的k[i]*c[i]之和;然后就是多重背包模板了,但是我用二进制拆分的模板却不对,用普通的反而过了。。。

[洛谷]P5365 [SNOI2017]英雄联盟 (#背包dp)_A.pro的博客-CSDN博客

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#include<ctime>
#define ll long long
#define CHECK(x,y) (x>0&&x<=n&&y>0&&y<=m)
const int inf=0x3f3f3f3f;
const int mod=1e9;
const int N=1e6+5;
using namespace std;
ll n,m,k[1000001],c[1000001];
ll dp[1000001];
int qb;
int main(){
   //freopen("in.txt","r",stdin);
    scanf("%lld%lld",&n,&m);
    qb=0;
    for(int i=1;i<=n;i++) scanf("%lld",&k[i]);
    for(int i=1;i<=n;i++) scanf("%lld",&c[i]),qb+=k[i]*c[i];
    dp[0]=1;
    /*for(int i=1;i<=n;i++){
        int num=min(k[i],qb/c[i]);
        for(int k=1;num>0;k<<=1){
            if(k>num) k=num;
            num-=k;
            for(int j=qb;j>=c[i]*k;j--)
                dp[j]=max(dp[j],dp[j-c[i]*k]*k),cout<<dp[j]<<endl;;

        }
    }*/
    for(int i=1;i<=n;i++)
        for(int j=qb;j>=c[i];j--)
        for(int p=1;p<=k[i]&&p*c[i]<=j;p++)
        dp[j]=max(dp[j],dp[j-c[i]*p]*p);
    int ans=0;
    while(ans<=qb&&dp[ans]<m) ans++;
    cout<<ans<<endl;
    return 0;
}

luogu p1156

        dp[j]代表高度为j时最长可存活的时间,把高度d看做是容量,如果dp[j]>=d了,直接输出a[i].t即可,如果不能逃出就把垃圾能吃就吃能活多长活多长

#include<bits/stdc++.h>
using namespace std;
struct rub{
    int t,f,h;
}a[110];
bool cmp(rub a,rub b){
    return a.t<b.t;
}
int main(){
    //freopen("in.txt","r",stdin);
    int d,g;
    int dp[110];
    scanf("%d%d",&d,&g);
    memset(dp,0,sizeof(dp));
    dp[0]=10;
    for(int i=1;i<=g;i++)
        scanf("%d%d%d",&a[i].t,&a[i].f,&a[i].h);
    sort(a+1,a+g+1,cmp);
    for(int i=1;i<=g;i++)
    for(int j=d;j>=0;j--)
    if(dp[j]>=a[i].t){
        if(j+a[i].h>=d){
            cout<<a[i].t<<endl;
            return 0;
        }
        dp[j+a[i].h]=max(dp[j+a[i].h],dp[j]);
        dp[j]+=a[i].f;//能吃就吃,此处修改dp[j]
        //的值并不影响dp[j+a[i].h]的值
    }
    cout<<dp[0]<<endl;
return 0;
}

luogu p1282

dp[i][j]代表前i个多米诺骨牌上下差为j时最小的翻转次数,去掉绝对值差值是在-5000-5000之间,数组不能为负值,所以平移一下数组,最后找出差值最小的最小翻转次数,小于等于1000就输出(因为最多能翻1000次,小于等于1000就是最小值了)

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
int dp[1005][10005];
int main(){
    //freopen("in.txt","r",stdin);
    int n,a[1005],n1,n2;

    scanf("%d",&n);

    for(int i=1;i<=n;i++){
        scanf("%d%d",&n1,&n2);
        a[i]=n1-n2;
    }
    int m=5000;//差最大就是5000
    memset(dp,inf,sizeof(dp));
    dp[0][m]=0;
    for(int i=1;i<=n;i++)
        for(int j=-m;j<=m;j++)
            //数组不能为负,所以数组平移一下
            dp[i][j+m]=min(dp[i-1][j+m-a[i]],dp[i-1][j+m+a[i]]+1);
               //前者代表不翻转,后者代表翻转
        int minn=inf;

        for(int i=0;i<=m;i++){
            //对可能的差遍历
            minn=min(dp[n][m+i],dp[n][m-i]);
            if(minn<=1000){
                cout<<minn<<endl;
                break;
            }
        }
return 0;
}

hdu5392

求解多个数的最小公倍数,题意就没看懂Orz,看的题解并没有快速幂,主要是如何求多个数的最小公倍数

HDU-5392-Infoplane in Tina Town_娃娃酱斯密酱的博客-CSDN博客

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#define ll long long
using namespace std;
const int inf=0x3f3f3f3f;
const int N=3e6+10;
const ll mod=3221225473;
int t,a[N],vis[N],num[N],n;
int main(){
    //freopen("in.txt","r",stdin);
    cin>>t;
    while(t--){
        scanf ("%d", &n);
		for (int i = 1; i <= n; i++)
		{
			scanf ("%d", &a[i]);
			vis[i] = 0;
			num[i] = 0;
		}
        for(int i=1;i<=n;i++){
            if(!vis[i]){
                int cnt=0;
                int k=i;
                while(!vis[k]){//求循环长度
                    vis[k]=1;
                    cnt++;
                    k=a[k];
                }
                for(int j=2;j*j<=cnt;j++){
                    int top=0;
                    if(!(cnt%j)){//求质因数
                        while(!(cnt%j)){
                            cnt/=j;
                            top++;
                        }
                    }
                    num[j]=max(num[j],top);//维护最高次幂的质因数
                }
                if(cnt>1){
                    num[cnt]=max(num[cnt],1);
                }
            }
        }
        ll res = 1;
		for (int i = 2; i <= n; i++)
		{
			while (num[i]--)
			{
				res = res * i % mod;
			}
		}
		cout << res << endl;
	}
return 0;
}

luogu p2224

dp[j]表示A机器用时j,B机器的用时,挨个判断每个任务用哪种情况更好

(1条消息) 洛谷 P2224 [HNOI2001]产品加工 解题报告_weixin_30940783的博客-CSDN博客

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#define ll long long
const int inf=0x3f3f3f3f;
using namespace std;
int main(){
    //freopen("in.txt","r",stdin);
    int n,c[4],dp[30005],r=0;
    scanf("%d",&n);
    memset(dp,inf,sizeof(inf));
    dp[0]=0;
    for(int i=1;i<=n;i++){
        scanf("%d%d%d",&c[0],&c[1],&c[2]);
        r+=max(c[0],max(c[1],c[2]));
        for(int j=r;j>=0;j--){
            if(c[1])//这个任务用b机器做
            dp[j]+=c[1];
            else dp[j]=inf;
            if(j>=c[0])//这个任务用a机器做
            dp[j]=min(dp[j],dp[j-c[0]]);
            if(j>=c[2])//这个任务a和b一起做
            dp[j]=min(dp[j],dp[j-c[2]]+c[2]);
        }
    }

        int ans=inf;
        for(int i=0;i<=r;i++)
            ans=min(ans,max(dp[i],i));//选A和B用时最长的,因为两台机器都做完才算做完
        cout<<ans<<endl;
return 0;
}

codeforce B Update Files

思路好像是对的,但是老是想不出那个代码的算式要怎么写,还是代码能力太差了,如果没有k限制的话,copy数是2的n次方递增的,所以看看mul一直乘以2小于k的次数cnt,然后n再减去mul,剩余的除以k再加上cnt就是答案,还有就是不要忘了取余

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#define ll long long
const int inf=0x3f3f3f3f;
using namespace std;
int main(){
    //freopen("in.txt","r",stdin);
    ll t,n,k;
    scanf("%lld",&t);
    while(t--){
        scanf("%lld%lld",&n,&k);
        ll cnt=0,mul=1;
        while(mul<k){
            cnt++;
            mul*=2;
        }
        if(mul<n)
        cnt+=(n-mul)/k+(((n-mul)%k)!=0);
        printf("%lld\n",cnt);
    }
return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

killer_queen4804

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值