2022/4/19

142 篇文章 0 订阅

Problem - D - Codeforces  求因子判断x/i要放if里面!!!

问有几种方案可以使得x可以被表示为x因子的乘积,并且这些因子要是漂亮数,因子可以重复使用,那就想到了完全背包了,先求出x的因子,然后用map或者是两个数组存一下值,两个数组的话大于1e5就放在gid这个数组里,小于等于就放在id这个数组里,转移的时候就靠下标转移,因为数太大了,把数当成容量的话数组放不下,还有一些详情注释有;

D. Madoka and the Best School in Russia (dp?)_Bzdhxs_nt的博客-CSDN博客

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int t,x,d,dp[100005],id[100005],gid[100005];
int maxx=1e5+10;
vector<int>v;
int main(){
    scanf("%d",&t);
    while(t--){
        v.clear();
        scanf("%d%d",&x,&d);
        for(int i=1;i*i<=x;i++){
            if(x%i==0){
                v.push_back(i);
                if(i!=x/i) v.push_back(x/i);//这句话一定要放在括号里面!!!
            }
        }
        sort(v.begin(),v.end());
        for(int i=0;i<v.size();i++){
            if(v[i]<=maxx) id[v[i]]=i;
            else gid[x/v[i]]=i;
        }
        for(int i=0;i<=v.size();i++) dp[i]=0;
        dp[0]=1;
        for(int i=0;i<v.size();i++){
            if(v[i]%d==0&&(v[i]/d)%d!=0){//只有是漂亮数才能进入循环
                //cout<<v[i]<<" "<<i<<endl;
                for(int j=0;j<v.size();j++){
                    if((x/v[i])%v[j]==0){//保证v[i]*v[j]也是x的因子
                    int u=v[i]*v[j],w=v[j];
                    int y=u>maxx?gid[x/u]:id[u];
                    int z=v[j]>maxx?gid[x/v[j]]:id[v[j]];
                    dp[y]+=dp[z];//用w来转移v[i]*v[j],从而也保证不会有错误的情况转移过去
                   // cout<<dp[mp[u]]<<" s "<<w<<" "<<v[i]<<endl;
                    }
                }
            }
        }
        if(dp[v.size()-1]>=2) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

Problem - C - Codeforces

这个题一开始想成了dp,但其实贪心就可以解决,每次攻占了一座城市就比较一下不更换的情况下攻占后面的城市所需要的花费和更换的情况下所需要的花费,如果后者更小就换城市;

Codeforces Round #782 (Div. 2) C. Line Empire - 知乎 (zhihu.com)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<list>
#include<stack>
#include<set>
#include<ctime>
//HDU专用火车头
//#include <bits/stdc++.h>
#define ll long long
#define lowbit(x) ((-x)&(x))
using namespace std;
const int mod=1000000007;
const ll inf=1e18;
const ll bou=1e15;
const int maxn=1e7+5;
ll qpow(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1) res*=a;
        a*=a;
        b>>=1;
    }
    return res;
}
ll t,n,a,b,c[200005],sum[200005];
int main(){
    //freopen("in.txt","r",stdin);
    scanf("%lld",&t);
    while(t--){
        scanf("%lld%lld%lld",&n,&a,&b);
        for(int i=1;i<=n;i++) scanf("%lld",&c[i]),sum[i]=sum[i-1]+c[i];
        ll pos=0,ans=0;
        for(int i=1;i<=n;i++){
            ans+=b*(c[i]-pos);
            if((sum[n]-sum[i]-(n-i)*pos)*b>=(sum[n]-sum[i]-(n-i)*c[i])*b+a*(c[i]-pos)){
                ans+=a*(c[i]-pos);
                pos=c[i];
            }
        }
        printf("%lld\n",ans);
    }
	return 0;
}

Problem - B - Codeforces

只想到了对一个数操作偶数次其他的位置不会变,而没有想到对一个位置操作的次数与总的次数之差如果是偶数就不会变,是奇数就会改变,那问题就变得比较简单了,如果k是奇数那么如果想要最大都是要从1开始遍历,如果s[i]==‘1’那么在位置i上操作的次数必然是奇数才好,那就让他为1,多了也没什么用,如果为0就让他为偶数0,剩下的次数全放在ans[n]中,这样会是最优的情况,偶数也是一样的道理;

Codeforces Round #782 (Div. 2) A~D - 知乎 (zhihu.com)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iomanip>
#include<map>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<list>
#include<stack>
#include<set>
#include<ctime>
//HDU专用火车头
//#include <bits/stdc++.h>
#define ll long long
#define lowbit(x) ((-x)&(x))
using namespace std;
const int mod=1000000007;
const ll inf=1e18;
const ll bou=1e15;
const int maxn=1e7+5;
ll qpow(ll a,ll b){
    ll res=1;
    while(b){
        if(b&1) res*=a;
        a*=a;
        b>>=1;
    }
    return res;
}
ll t,n,k,ans[200005];
string s;
int main(){
    //freopen("in.txt","r",stdin);
    scanf("%lld",&t);
    while(t--){
        scanf("%lld%lld",&n,&k);
        ll x=k;
        cin>>s;s=" "+s;
        for(int i=1;i<=n;i++) ans[i]=0;
        if(k&1){
            for(int i=1;i<=n;i++){
                if(x<=0) break;
                if(s[i]=='1'){
                    ans[i]=1,x--;
                }
            }
            if(x>0) ans[n]+=x;
        }
        else{
            for(int i=1;i<=n;i++){
                if(x<=0) break;
                if(s[i]=='0') ans[i]=1,x--;
            }
            if(x>0) ans[n]+=x;
        }
        for(int i=1;i<=n;i++){
            if((k-ans[i])&1){
                s[i]=s[i]=='1'?'0':'1';
            }
            cout<<s[i];
        }
        cout<<endl;
        for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
        cout<<endl;
    }
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

killer_queen4804

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

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

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

打赏作者

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

抵扣说明:

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

余额充值