CodeCraft-21 and Codeforces Round #711 (Div. 2) A~C题解


原题链接

A. GCD Sum(思维+暴力)

解题思路

这道题我们直接遍历判断即可,为什么呢?我们总能确定在遍历的过程中不会遍历太久,因为如果对应的 n n n一直增 1 1 1,在这个过程中会存在 d i g i t _ s u m digit\_sum digit_sum n n n都是为偶数的。当然,这还是我们不考虑其他的情况下,因为我们要的只要满足 g c d gcd gcd大于 1 1 1,所以可以肯定的暴力即可。

AC代码

/**
  *@filename:A
  *@author: pursuit
  *@CSDNBlog:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-03-30 14:42
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;

int t;
ll n;
ll gcd(ll n,ll m){
    return n%m?gcd(m,n%m):m;
}
ll digit_sum(ll n){
    ll ans=0;
    while(n>0){
        ans+=n%10;
        n/=10;
    }
    return ans;
}
void solve(){
    while(true){
        if(gcd(n,digit_sum(n))>1){
            cout<<n<<endl;
            break;
        }
        n++;
    }
}
int main() {
    while(cin>>t){
        while(t--){
            cin>>n;
            solve();
        }
    }
    return 0;
}

B.Box Fitting(贪心)

解题思路

这道题就是纯粹的贪心,我们总想极大化的利用剩余空间,所以我们可以记录每一层的剩余空间,利用优先队列将这些存储起来,这样的好处就是我们每次都可以取到最大的剩余空间,以便我们知道还需不需要增加层数。 那么对应的方格,由于它们的高度就为 1 1 1,且由于方格不能进行旋转放置,所以我们只能水平放置,这样我们只关心它的长度,我们需要将它们的长度进行降序排列,然后我们直接遍历即可,如果空间不够,就加一层存储,所以最后优先队列的大小即是我们最小盒子的高度。

AC代码

/**
  *@filename:B
  *@author: pursuit
  *@CSDNBlog:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-03-30 15:17
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 100000 + 5;
const int mod = 1e9+7;

int t,n,w;
bool cmp(int a,int b){
    return a>b;
}
void solve(vector<int> &a){
    sort(a.begin(),a.end(),cmp);
    priority_queue<int> q;//优先队列,存放剩余空间。
    q.push(w);//放入一块初始空间。
    for(int i=0;i<n;i++){
        //接下来开始判断剩余空间是否够用。
        if(q.top()<a[i]){
            q.push(w-a[i]);//不够用就要再加入一层。
        }
        else{
            //够用就更新剩余空间大小。
            int temp=q.top()-a[i];
            q.pop();
            q.push(temp);
        }
    }
    cout<<q.size()<<endl;
}
int main() {
    while(cin>>t){
        while(t--){
            cin>>n>>w;
            vector<int> a(n);
            for(int i=0;i<n;i++){
                cin>>a[i];
            }
            solve(a);
        }
    }
    return 0;
}

C. Planar Reflections(动态规划)

题意

由于这道题可能题意比较难理解,所以这里解释一下。题目中说明初始时有一个衰减年龄为 k k k的粒子,同时在它的前进方向有 n n n的平面,当粒子经过一个平面后,如果粒子的衰减年龄 k k k大于 1 1 1,那么它就会往相反的方向产生一个衰减年龄为 k − 1 k-1 k1的粒子。 问这样的一个粒子最终能够产生多少个粒子?
例如对于 n = 2 , k = 3 n=2,k=3 n=2,k=3的时候,如下图:
在这里插入图片描述
我们发现这样的一个粒子最后能得到 4 4 4个粒子。

解题思路

我们还是继续分析这个样例,我们发现,这样拆分之后其实就像是一个状态被分解一样。我们可以定义这样的一个状态: d p [ i ] [ j ] dp[i][j] dp[i][j],它表示运动前方还有k个平面,且衰变年龄为j的粒子所能产生的粒子数量。
那么样例中的 d p [ 2 ] [ 3 ] dp[2][3] dp[2][3],它反弹后的粒子状态为 d p [ 0 ] [ 2 ] dp[0][2] dp[0][2](由于反弹,方向改变,所以运动前方剩余平面为 n − i n-i ni个),它继续往前的状态为 d p [ 1 ] [ 3 ] dp[1][3] dp[1][3],即 d p [ 2 ] [ 3 ] = d p [ n − i ] [ 3 − 1 ] + d p [ 2 − 1 ] [ 3 ] dp[2][3]=dp[n-i][3-1]+dp[2-1][3] dp[2][3]=dp[ni][31]+dp[21][3]
那么这就显而易见了,答案是 d p [ n ] [ k ] dp[n][k] dp[n][k],到这一步我们最关键的就是将初始状态给找出来,对于衰变年龄为1的粒子,它不过经过多少个平面,所能产生的粒子就是它本身。而对于运动前方没有平面的粒子,是不能分裂的。粒子数量只有它本身。 即初始状态如下:

for(int i=1;i<=n;i++){
    dp[i][1]=1;
}
for(int j=1;j<=k;j++){
    dp[0][j]=1;
}

值得注意的一点就是在处理状态转移的时候,我们为了通过前面状态得到后面状态就必须先推出 j − 1 j-1 j1 1 1 1~ n n n所有情况,因为我们在 j j j的时候会引用到 n − i n-i ni,这样就会造成错误。

AC代码

/**
  *@filename:C
  *@author: pursuit
  *@CSDNBlog:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-03-30 15:37
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 1000 + 5;
const int mod = 1e9+7;

int t,n,k;//n个平面,k表示为衰变年龄。
int dp[maxn][maxn];//定义状态:用dp[i][j]表示运动前方还有k个平面,且衰变年龄为j的粒子所能产生的粒子数量。
void solve(){
    memset(dp,0,sizeof(dp));
    //初始状态,对于衰变年龄为1的粒子,它不过经过多少个平面,所能产生的粒子就是它本身。
    for(int i=1;i<=n;i++){
        dp[i][1]=1;
    }
    //对于运动前方没有平面的粒子,是不能分裂的。粒子数量只有它本身。
    for(int j=1;j<=k;j++){
        dp[0][j]=1;
    }
    //为了通过前面状态得到后面状态,所以我们先要推出j的所有情况。
    for(int j=1;j<=k;j++){
        for(int i=1;i<=n;i++){
            dp[i][j]=(dp[i-1][j]+dp[n-i][j-1])%mod;
        }
    }
    cout<<dp[n][k]<<endl;
}
int main() {
    while(cin>>t){
        while(t--){
            cin>>n>>k;
            solve();
        }
    }
    return 0;
}
posted @ 2022-03-26 16:49  unique_pursuit  阅读(17)  评论(0)    收藏  举报