codeforce 894

这篇具有很好参考价值的文章主要介绍了codeforce 894。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

A. Gift Carpet (模拟)

题意:
给出n*m的矩阵,从左到右每列最多取一个字母,问能否取出"vika"
思路:
直接模拟。

const int N=1e6+10;
char g[25][25];
void solve(){
    int n,m; cin>>n>>m;
    string s="vika";
    for(int i=0;i<n;i++){
        getchar();
        for(int j=0;j<m;j++){
            g[i][j]=getchar();
        }
    }
    int j=0;
    bool flag=true;
    for(char c:s){
        bool ok=false;
        for(;j<m;j++){
            for(int i=0;i<n;i++){
                if(g[i][j]==c){
                    ok=true;
                    break;
                }
            }
            if(ok) {
                j++;
                break;
            }
        }
        if(!ok) {
            flag=false;
            break;
        }
    }
    if(flag) printf("YES\n");
    else printf("NO\n");
}
int main(){
    int t; cin>>t;
    while(t--){
        solve();
    }
}   

B. Sequence Game (构造)

题意:
假设有一个序列a1…an, 我们要根据题目给出的序列b1…bm猜出序列a1…an。b1…bm是这样来的:

  • b1 == a1
  • 遍历a2…an,如果发现 a i − 1 < = a i {a_{i-1}<=a_{i}} ai1<=ai ,则将 a i {a_i} ai加入b序列。

比如a序列是 4 , 3 , 2 , 6 , 3 , 3 4,3,2,6,3,3 4,3,2,6,3,3,那么对应的b序列是 4 , 6 , 3 4,6,3 4,6,3。现在给出b序列,要求输出a序列。

思路:
构造出一个符合条件的序列即可。a序列如果是 4 , 6 , 6 , 3 4,6,6,3 4,6,6,3,那么就能得到 4 , 6 , 3 4,6,3 4,6,3这样的b序列。

const int N=2e5+10;
int a[N];
void solve(){
    int n; cin>>n;
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    vector<int> res;
    res.push_back(a[0]);
    for(int i=1;i<n;i++){
        if(a[i-1]>a[i]) res.push_back(a[i]);
        res.push_back(a[i]);
    }
    printf("%d\n",res.size());
    for(int i=0;i<res.size();i++){
        if(i==0) printf("%d",res[i]);
        else printf(" %d",res[i]);
    }
    printf("\n");
}
int main(){
    int t; cin>>t;
    while(t--){
        solve();
    }
}   

C. Flower City Fence (模拟)

题意
给出一个序列 a 1.. a n a1..an a1..an,那么在xy坐标轴上面可以形成一个柱状图:
codeforce 894,算法
然后题目问你,如果把它转置之后(行转成列,列变成行)是否能得到一样的柱状图。
codeforce 894,算法

思路
令转置之前的高度序列为 H 1 , H 2 . . . H n H_{1}, H_2 ... H_n H1,H2...Hn
转置之后的高度序列为 h 1 , h 2... h m h_1,h2...h_m h1,h2...hm
然后比较这两个序列是不是相同就可以了。

const int N=2e5+10;
int a[N];
void solve(){
    int n; cin>>n;
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    if(a[0]!=n){
        printf("NO\n");
        return;
    }
    vector<int> b(n);
    int p=n;
    for(int h=0;h<n;h++){
        for(;p>=0;){
            if(a[p-1]>h) break;
            else p--;
        }
        b[h]=p;
    }
    bool ok=true;
    for(int i=0;i<n;i++){
        if(a[i]!=b[i]){
            ok=false;
            break;
        }
    }
    if(ok) printf("YES\n");
    else printf("NO\n");
}
int main(){
    int t; cin>>t;
    while(t--){
        solve();
    }

D. Ice Cream Balls

题意
两个材料可以制作出一种冰淇淋。例如:
1 , 1 , 2 {1,1,2} 1,1,2为原材料,能制作出 1 , 1 {1,1} 1,1 1 , 2 {1,2} 1,2 两种不同类型的冰淇淋。
现在假设有x个材料,刚好能制作出n冰淇淋。题目给出n,求x。

思路
我们将n*(n-1)/2的序列打印出来看,能发现一些规律:

2*(2-1)/2=1
3*(3-1)/2=3
4*(4-1)/2=6
5*(5-1)/2=10
6*(6-1)/2=15
7*(7-1)/2=21
8*(8-1)/2=28
9*(9-1)/2=36
10*(10-1)/2=45
11*(11-1)/2=55

1 , 2 {1,2} 1,2可以制作出1种;
1 , 2 , 3 {1,2,3} 1,2,3可以制作出3种;
1 , 2 , 3 , 4 {1,2,3,4} 1,2,3,4可以制作出6种。
但是题目给出的n有可能不是 n ∗ ( n − 1 ) / 2 n*(n-1)/2 n(n1)/2,比如要制作5种,那么就得构造 1 , 2 , 3 , 2 , 3 1,2,3,2,3 1,2,3,2,3,那么n=5对应的x就是5。
也就是说n=5的时候,

  1. 我们先找到x=3,由于 3 ∗ ( 3 − 1 ) / 2 = 3 3*(3-1)/2=3 3(31)/2=3,还差2种
  2. 那么x=3+2=5.

关于n=5的时候怎么找到x=3,我这里用了二分,但是看别人的题解好像不用二分直接从1开始暴力找也行。

void solve(){
    ll n; cin>>n;
    ll l=1,r=1e10;
    ll ans=0;
    while(l<=r){
        ll mid=(l+r)/2;
        if(mid*(mid-1)/2 <= n){
            ans=mid;
            l=mid+1;
        } else {
            r=mid-1;
        }
    }
    ans+=(n-ans*(ans-1)/2);
    printf("%lld\n",ans);
}
int main(){
    int t; cin>>t;
    while(t--){
        solve();
    }
}   

E. Kolya and Movie Theatre (补)

题意
给出一个整数d=2,m=2,再给出一个数组 3 , 2 , 5 , 4 , 6 3,2,5,4,6 3,2,5,4,6
最多可以选m个数,然后得到一个分数sum。这个sum怎么算呢,比如我选了3和5这两个数:

  • s u m + = 3 − d sum += 3 - d sum+=3d
  • s u m + = 5 − 2 ∗ d sum += 5 - 2*d sum+=52d

第一次选3的时候距离上一次选的距离是1,所以减去d;
第二次选5的时候距离上一次选的距离是2,所以减去2*d;
所以这么选最终得到的分数就是 3 − 2 ∗ 1 + 5 − 2 ∗ 2 = 2 3-2*1 + 5 -2*2 = 2 321+522=2
求最大能得到的分数。

思路
dp[i]表示以a[i]结尾序列的最大分数,那么 a n s = m a x ( d p [ i ] ) ans=max(dp[i]) ans=max(dp[i])


int a[N];
void solve(){
    int n,m,d; cin>>n>>m>>d;
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    priority_queue<int,vector<int>,greater<int>> pq;
    ll sum=0,sd=0;
    ll ans=0;
    for(int i=0;i<n;i++){
        int delta=a[i]-((i+1)*d-sd); // 选a[i]的贡献
        sum+=delta; pq.push(a[i]);
        // 把前面贡献度小于0的元素删掉
        // 如果选择超过了m个,删掉贡献度比较低的元素
        while((!pq.empty()&&pq.top()<=0) || pq.size()>m) {sum-=pq.top(); pq.pop();} 
        sd=(i+1)*d; 
        ans=max(ans,sum); 
    }
    printf("%lld\n",ans);
   
}
int main(){
    // freopen("input.txt","r",stdin);
    int t; cin>>t;
    while(t--){
        solve();
    }
}   

F. Magic Will Save the World (补)

写了个暴力,尝试剪了一下枝还是没过(恼),就知道要换种思路了。

const int N=210;
int a[N];
bool flag;
void dfs(int rw,int rf,int i,int n){
    if(rw<0||rf<0||flag) return;
    if(i==n){
        flag=true;
        return;
    }
    dfs(rw-a[i],rf,i+1,n);
    dfs(rw,rf-a[i],i+1,n);
}
void solve(){
    int w,f,n; cin>>w>>f>>n;
    ll sum=0;
    for(int i=0;i<n;i++) {
        scanf("%d",&a[i]);
        sum+=a[i];
    }

    ll l=sum/(w+f),r=sum/min(w,f)+10;
    ll ans=0;
    for(;l<=r;){
        ll mid=(l+r)>>1;
        if(mid*w+mid*f<sum) {
            l=mid+1;
            continue;
        }
        flag=false;
        dfs(mid*w,mid*f,0,n);
        if(flag){
            ans=mid;
            r=mid-1;
        } else {
            l=mid+1;
        }
    }
    printf("%d\n",ans);
}

int main(){
    // freopen("input.txt","r",stdin);
    int t; cin>>t;
    while(t--){
        solve();
    }
}   

看了题解之后发现可以基于01背包枚举monster数组所有可能的子序列和,然后遍历,得到最优答案。文章来源地址https://www.toymoban.com/news/detail-673862.html

const int N=110;
const int CMAX=N*(1e4+1);
int c[N];
int dp[CMAX];
int _div(int x,int y){
    return (x+y-1)/y;
}
void solve(){
    memset(dp,0,sizeof(dp));
    int w,f,n; cin>>w>>f>>n;
    int sum=0;
    for(int i=1;i<=n;i++) {cin>>c[i]; sum+=c[i];}
    dp[0]=1;
    int ans=INT32_MAX;
    for(int i=1;i<=n;i++){
        for(int j=sum;j>=0;j--){
            if(j-c[i]>=0) dp[j]|=dp[j-c[i]];
            if(dp[j]){ 
                ans=min(ans, max(_div(j,w),_div(sum-j,f))); 
            }
        }
    }
    cout<<ans<<endl;
}

int main(){
    int t; cin>>t;
    while(t--){
        solve();
    }
}   

到了这里,关于codeforce 894的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 「Codeforces」A. Reverse

    2022年2月15日15:29:19 题目描述 给一个长度为 n 序列, p 1 , p 2 , … , p n p_1, p_2, dots, p_n p 1 ​ , p 2 ​ , … , p n ​ 。选择两个整数,即一个区间 [ L , R ] [L, R] [ L , R ] ,对其区间进行反转操作。 要求你找到恰好执行一次反转操作获得的字典最小序列。 序列是一个数组,由 1 到

    2024年02月02日
    浏览(50)
  • CodeForces1061C Multiplicity

    从序列 ({a_1, a_2, .. , a_n}) 中选出 非空 子序列 ({b_1, b_2, .. , b_k}) ,一个子序列合法需要满足 (forall i in [1, k], i | b_i) 。求有多少互不相等的合法子序列,答案对 (10^9 + 7) 取模。 序列 ({1, 1}) 有 (2) 种选法得到子序列 ({1}) ,但 (1) 的来源不同,认为这

    2024年02月05日
    浏览(41)
  • codeforces补题 1.0

    B----https://codeforces.com/contest/1872/problem/B 翻译: 你位于一个无限延伸向右的走廊中,走廊被分割成方形的房间。你从房间1出发,前往房间k,然后返回房间1。你可以选择k的值。移动到相邻的房间需要1秒。 此外,走廊中有n个陷阱:第i个陷阱位于房间di,并且在你进入房间di后

    2024年02月09日
    浏览(27)
  • Codeforces 918(div4)

    注意一下判断 是否为平方数的方法;也要记得开long long 正序写 讨论的情况比较多,所以选择倒叙看;

    2024年02月03日
    浏览(37)
  • CodeForces CF1846G 题解

    CodeForces题目链接 洛谷题目链接 标准答案是状压之后,转化成Dijkstra算法跑最短路。我这里提供一个不一样的思路。 主人公得了病,有部分类型的症状。所有类型症状共有 (n) 种,用长为 (n) 的01串表示是否有那种症状。共有 (m) 种药,吃第 (i) 种药需要花费时间 (t_i) ,

    2024年02月14日
    浏览(31)
  • Codeforces 1855E 数学期望 + DP

    题意 传送门 Codeforces 1855E Expected Destruction 题解 将 S i S_i S i ​ 运动至 S i + 1 S_{i+1} S i + 1 ​ 的情况看作后者消失,则 S i S_i S i ​ 在碰到 S i + 1 S_{i + 1} S i + 1 ​ 前, S i + 1 S_{i + 1} S i + 1 ​ 必然存在。 根据数学期望的线性性质,可以独立地考虑每一个 S i S_i S i ​ 在碰到 S i

    2024年02月06日
    浏览(30)
  • 【Codeforces】 CF79D Password

    CF方向 Luogu方向 看到区间异或,一个经典的套路是做差分,我们即在 l l l 处异或一次,在 r + 1 r+1 r + 1 处异或一次,然后前缀和起来 于是我们可以将问题转化成:有一个序列初始全 0 0 0 ,每次可以把相隔 a i a_i a i ​ 的数都 ⊕ 1 oplus 1 ⊕ 1 ,求最少将其变成一个状态的步数

    2024年02月08日
    浏览(27)
  • Codeforces Round 881 (Div. 3)

    给定一个数组,给每个元素涂色。求最大的代价。 代价为每个颜色的代价和。 每个颜色的代价为涂了该颜色的元素的极差。 因为是极差,每个元素要么对答案有正的贡献,要么有负的贡献,要么无贡献。且正负贡献的个数要相同。 因为要最大值,自然就是想有正贡献的是最

    2024年02月09日
    浏览(32)
  • Codeforces Round 871 (Div. 4)

    给定n个长度为10的字符串,问其与codeforces字符串的对应下标字母不同的个数。 对于每个字符串从前往后依次和“codeforces”对应字符比较然后统计不同字母数即可 给定长度为n的数组,问连续相邻为0的最大长度 维护一个全局最大长度res,和当前连续序列的长度cnt。从前往后扫

    2024年02月03日
    浏览(44)
  • Codeforces Round 867 (Div. 3)

    从所有a[i]+i-1=t的选择种取个max即可 实际上就是取同符号乘积的最大值 找规律,发现结果与边长n的关系是:res = n * (n + 3) - (n - 2) ①当n为奇数时,除了1其他均无解 ②当n为偶数时,我们可以构造一个形如n,1,n - 2,3,...的数列 首先我们可以发现n必定出现在起始位置。如果n不在起

    2024年02月02日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包