开学过半 (cf补题和算法训练)

 

Problem - D - Codeforces

题意:

给你一个n和一个k,让你找到1到k里的一个数x,让n*x得出的结果尾巴的0要尽可能地多

如果无论这么搞都没有,那么就输出n*k即可

 

题解:

 我们先想一下  0是怎么来的

是不是由2*5得来,所以我们想要更多地0,我们就需要在n里面找多余地2和5

里面地2和5会相互成0,所以我们找出多余地,然后用在x里面乘就行了,就是用x里面地2  或者   5去帮n补0

这个就是分离因子地思想

然后统计一下10

最后m/x*x就是在k里面找地最大数咯

#include <bits/stdc++.h>
#pragma  GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
//#define endl '\n';
using namespace std;
const int N=2e5+7,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=100003;
typedef pair<int,int> PII;

int a[N];
int n,m;
void solve()
{

    cin>>n>>m;
    int t=n;

    int ans2=0,ans5=0;
    while (t%2==0)
    {
        ans2++;
        t/=2;
    }
    t=n;
    while (t%5==0)
    {
        ans5++;
        t/=5;
    }
    int x=1;
    while (ans2>ans5 && x*5<=m)
    {
        x*=5;
        ans2--;
    }
    while (ans2<ans5 && x*2<=m)
    {
        x*=2;
        ans5--;
    }

    while (x*10<=m)
    {
        x*=10;
    }

    cout<<m / x * x * n<<'\n';
}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 

Problem - B - Codeforces

题意:给你一个进制p和一串数字,然后你可以断加一在尾数,要是满则进一

现在要求你实现,要出现0到p-1的数字,问你需要加几次

 

题解:一看就只有两种情况

首先我们用map统计出现的数字

一:就是尾数之前的数字都存在我们只需要尾数不断加一向前跑,不需要进位,就可以出现所以数,答案就是最后一个出现的数减尾数

 

二:就是需要进位,那没进位时我们需要模拟过程,把进位过程中出现的数字都标记

然后在由0跑的尾数即可

(注意如果前面没有数字的时候,如果第一个数字满足了p,我们需要多搞出一位这一位等于1)标记1

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
//#define endl '\n';
using namespace std;
const int N=300010,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=1e9+7;
typedef pair<int,int> PII;
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};


int a[N];

void solve()
{
     int n,p;
     cin>>n>>p;
     map<int,int> mp;
     a[0]=0;
     for(int i=1;i<=n;i++)
     {
         cin>>a[i];
         mp[a[i]]=1;
     }
     int f=0;
     for(int i=0;i<a[n];i++)
     {
         if(!mp[i])
         {
             f=1;
             break;
         }
     }
     if(f!=1)
     {
         int ans=p-1;
         while (mp[ans]) ans--;
         cout<<max(0ll,ans-a[n])<<endl;
     }
     else
     {
         int x=0;
         x+=p-a[n];
         mp[0]=1;

         int ans=0;
         int y=a[n]-1;
         a[n]=0;
         for(int i=n-1;i>=1;i--)
         {
             a[i]++;
             ans++;
             if(a[i]==p) a[i]=0;
             mp[a[i]]=1;
            if(a[i]) break;
         }
         if(ans==n-1 && a[1]==0) mp[1]=1;

         while (mp[y])
         {
             y--;
         }
         x+=max(0ll,y);
         cout<<x<<endl;
     }

}

signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 Problem - C - Codeforces

题意:给你一个n*m的矩阵,里面只有0和1 ,然后你需要从1,1点到n,m 点,你走的路径必须全部是回文串,就是第一个和最后一个位置的数字相等

倒数第二个和第二格相等,以此类推,要让全部可行路径都的是回文的,你可以改变某个位置的0或者1

现在让你通过最少改变的次数实现全部路径都是回文的

 

题解:我们想一下,这里的意是回文就是(1,1)和(n,m)对应   (1,2)和(n-1,m)  或者(n,m-1) 对应,所以我们发现前面的点加后面的对应点无论如何的等于

x1+y1+x2+y2=n+m+2,所以我们可以推出目标点x2+y2=n+m+2-x1-x1 这样我们就可以找出对应点了,让这些对应点都等于对应点集合里最大数即可

所以我们用一个数组存1和0的个数,然后把一和0全加上在删除最大个数就是答案

 

这里注意,如果回文是个基数串,中间的就不需要改变,所以就不要遍历到(n+m+2)/2(这个的意思是集合里面就有这么多个集合)

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
#define endl '\n';
using namespace std;
const int N=1000,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=1e9+7;
typedef pair<int,int> PII;
int dx[4]={1,-1,0,0};
int dy[4]={0,0,1,-1};

int a[N][N];
int num[N][2];
void solve()
{
    int n,m;
    cin>>n>>m;
    ::memset(num,0,sizeof (num));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
            if(a[i][j]==0)
            {
                num[i+j][0]++;
            }
            else
            {
                num[i+j][1]++;
            }
        }
    }
    int ans=0;
    if((n+m)%2==1)
    {
        for(int i=2;i<=(n+m+2)/2;i++)
        {
            ans+=num[i][0]+num[i][1]+num[n+m+2-i][0]+num[n+m+2-i][1]-max(num[i][0]+num[n+m+2-i][0],num[i][1]+num[n+m+2-i][1]);
        }
    }
    else
    {
        for(int i=2;i<(n+m+2)/2;i++)
        {
            ans+=num[i][0]+num[i][1]+num[n+m+2-i][0]+num[n+m+2-i][1]-max(num[i][0]+num[n+m+2-i][0],num[i][1]+num[n+m+2-i][1]);
        }
    }
    cout<<ans<<endl;


}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 

posted @ 2023-10-11 16:47  whatdo+  阅读(2)  评论(0编辑  收藏  举报