Codeforces 每日一练 735D+573B+374C

735D Taxes

传送门
镜像传送门
数论题(1600)
Mr. Funt有收入为n,他为了减少自己需要缴纳的税额(DD行为),想要把收入分成k份(每份收入>1),每份单独缴税。对于每份收入,需要缴纳的税款为其最大因子(不为自己,如果是质数就是1)。帮助Mr. Funt最小化他缴纳的税款。
首先如果n为质数就可以不分了,1一定是最小的。
对于偶数,结果必定大于等于2,分两个质数就是2,分一个两个偶数就大于2,根据哥德巴赫猜想,任一大于2的偶数都可写成两个素数之和,那么偶数的答案就是2。
对于奇数,必定会分成一奇一偶,而偶数小于等于2(2的情况为1),而且一定可以找到一个质数充当分出来的质数,那么奇数的答案就是小于等于3,如果奇数-2为质数,那么就取最小值2,其他情况为3.
(就当补充知识树了~~

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);
#define maxn 5005
#define inf 1000000002
#define for_(i,n) for(ll (i)=1;(i)<=(n);i++)
#define mod 80112002
int n,m;
int is_prome(int n){
    for (int i = 2; i <=sqrt(n) ; ++i) {
        if(n%i==0)return 0;
    }
    return 1;
}
int main(){
    IOS
    cin>>n;
    if(is_prome(n)){cout<<1;return 0;}
    if(n%2==0)cout<<2;
    else{
        if(is_prome(n-2))cout<<2;
        else cout<<3;
    }
    return 0;
}

573B Bear and Blocks

传送门
镜像传送门
dp水题(迫真
1800
Limak是只小熊,他堆了一行塔,每座塔都有相应的高度,每次Limak可以把所有没有被完全包围的砖块摧毁,询问要多少次才能将所有塔摧毁(tm熊的力量!(滑稽))
什么是完全包围呢,如图:
在这里插入图片描述
(黑色部分即为被完全包围的砖块。)
根据题意,我们可以很快得到几条规律:
1、高度为1的在第1轮就毁掉
2、第i座塔最多存活h[i]轮(每座塔最上面的砖块每轮必被摧毁)
3、从左向右扫,第i+1座塔最多比第i座塔多存活1轮,从右向左同理
现在转移方程就很好写了,开两个数组存分别存从左到右和从右到左(规律3)每座塔的存活轮数,那每个塔的存活轮数就是两个数组中对应位置的最小值,最后遍历每座塔取一个最大值就好了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);
#define maxn 100005
#define inf 1000000002
#define for_(i,n) for(ll (i)=1;(i)<=(n);i++)
#define mod 80112002
int n;
int h[maxn],l[maxn],r[maxn];
int main(){
    IOS
    cin>>n;
    for_(i,n)cin>>h[i];
    l[1]=r[n]=1;
    for_(i,n){
        if(i==1)continue;
        if(h[i]==1){
            l[i]=1;
        }else{
            l[i]=l[i-1]+1;
        }
        l[i]=min(l[i],h[i]);
    }
    for (int j = n-1; j >=1 ; --j) {
        if(h[j]==1)r[j]=1;
        else r[j]=r[j+1]+1;
        r[j]=min(r[j],h[j]);
    }
    int ans=-1;
    for_(i,n){
        //cout<<l[i]<<" "<<r[i]<<endl;
        ans=max(ans,min(l[i],r[i]));
    }
    cout<<ans;
    return 0;
}

374C Inna and Dima

点这里去这道题恰狗粮
点这里去恰镜像狗粮
dfs+dp(2000)
Inna和Dima买了一张n*m的桌子,每个格子里都写有D、I、M、A中某个字母,Inna特别爱Dima,所以Inna想从某个D开始按照D-I-M-A-D-I……的顺序经过尽量多完整的“DIMA”,如果一个都没有,那么输出“Poor Dima!”,如果可以一直走下去(存在环),输出“Poor Inna!”,否则输出最多能走的个数。
先处理给的方格图,对走向合法的组合连单向边,开个dp存到当前节点的最长路径长度,然后从每个D开始dfs就好,但是会T,加个剪枝就好了,如果下一个节点的dp可以更新,就dfs下一个节点。最后取所有A的最大值除以4即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define IOS ios_base::sync_with_stdio(false);cin.tie(0);
#define maxn 1005
#define inf 1000000002
#define for_(i,n) for(ll (i)=1;(i)<=(n);i++)
#define mod 80112002
int dir[4]={1,-1,0,0},dir2[4]={0,0,1,-1};
int n,m;
struct node{
    int x,y;
};
node cc[maxn*maxn];
vector<int> g[maxn*maxn];
int d[maxn*maxn],num[maxn][maxn],vis[maxn*maxn],dp[maxn*maxn];
char s[maxn][maxn];
void link(int v){
    int x=cc[v].x,y=cc[v].y;
    for (int i = 0; i <4 ; ++i) {
        if(x+dir[i]<1||x+dir[i]>n||y+dir2[i]<1||y+dir2[i]>m)continue;
        int u=num[x+dir[i]][y+dir2[i]];
        if(s[x][y]=='D'&&s[x+dir[i]][y+dir2[i]]=='I'){g[v].push_back(u);d[u]++;}
        if(s[x][y]=='I'&&s[x+dir[i]][y+dir2[i]]=='M'){g[v].push_back(u);d[u]++;}
        if(s[x][y]=='M'&&s[x+dir[i]][y+dir2[i]]=='A'){g[v].push_back(u);d[u]++;}
        if(s[x][y]=='A'&&s[x+dir[i]][y+dir2[i]]=='D'){g[v].push_back(u);d[u]++;}
    }
}
void dfs(int x){
    vis[x]=1;
    for (auto i:g[x]){
        if(vis[i]&&s[cc[i].x][cc[i].y]=='D'){
            cout<<"Poor Inna!";
            exit(0);
        }
        if(dp[i]<dp[x]+1){
            dp[i]=max(dp[i],dp[x]+1);
            dfs(i);
        }
    }
    vis[x]=0;
}
int main(){
    IOS
    cin>>n>>m;
    for_(i,n)cin>>(s[i]+1);
    int cnt=1;
    for_(i,n){
        for_(j,m){
            num[i][j]=cnt;
            cc[cnt].y=j;
            cc[cnt++].x=i;
        }
    }
    for_(i,cnt){link(i);}
    queue<int> q;
    for_(i,cnt){
        if(s[cc[i].x][cc[i].y]=='D'){dp[i]=1;q.push(i);}
    }
    while(!q.empty()){
        int x=q.front();
        q.pop();
        dfs(x);
    }
    int ans=0;
    for_(i,cnt){
        if(s[cc[i].x][cc[i].y]=='A')ans=max(ans,dp[i]);
    }
    if(ans==0){cout<<"Poor Dima!";return 0;}
    cout<<ans/4;
    return 0;
}
posted @ 2020-03-19 17:28  Bazoka13  阅读(104)  评论(0编辑  收藏  举报