Round 1013(Div.3)DEF

Round 1013(Div.3)

D. Place of the Olympiad

题意:给一个 n ∗ m n*m nm 的网格黑白染色,使得恰好有 k k k个黑格子,且同一行连续黑格子数的最大值最小

题解:二分连续格子的最大值,显然放连续的格子是最优的,check的时候我们贪心的放最大连续格子,能放就放,注意后面的空格还能再放。

void solve(){
    int n,m,k;
    cin>>n>>m>>k;
    auto check = [&](int x){
        int l=1,r=m;
        while(l<r){
            int mid = l+r+1>>1;
            if((mid*x+mid-1)<=m)l=mid;
            else r=mid-1;
        }
        int cnt = m-(l*x+l);
        if(cnt<0)cnt=0;
        if(l*x*n+cnt*n>=k)return 1;
        else return 0;
    };
    int l=1,r=m;
    while(l<r){
        int mid = l+r>>1;
        if(check(mid))r=mid;
        else l = mid+1;
    }
    cout<<l<<"\n";
}

E. Interesting Ratio(欧拉筛)

题意:给定 n n n,求满足 l c m ( i , j ) / g c d ( i , j ) lcm(i,j)/gcd(i,j) lcm(i,j)/gcd(i,j)是质数的无序对个数。
题解:显然,对于每个数 a a a 只需要求 a = p ∗ b a=p*b a=pb 的个数,其中 p p p是质数
跑一遍欧拉筛把 1 e 7 1e7 1e7内的所有质数筛出来,然后再用埃氏筛,把每个数的质数约数的个数求出来即可,递推一遍就可以得到 [ 1 , 1 0 7 ] [1,10^7] [1,107]的答案。

#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;

const int N = 1e7+10;
const int M = 7e5+10;
vector<int> p;
int st[N+10],cnt[N],ans[N];
void init(){
    st[1]=1;
    for(int i=2;i<=N;i++){
        if(!st[i])p.push_back(i);
        for(int j=0;p[j]<=N/i;j++){
            st[i*p[j]]=1;
            if(i%p[j]==0)break;
        }
    }
    for(auto v:p){
        for(int i=v;i<N;i+=v){
            cnt[i]++;
        }
    }
    for(int i=1;i<N;i++){
        ans[i]=ans[i-1]+cnt[i];
    }
}

void solve(){
    int n;
    cin>>n;
    cout<<ans[n]<<"\n";
}


int32_t main(){
    ios::sync_with_stdio(false),cin.tie(nullptr);
    init();
    int _ = 1;
    cin>>_;
    while(_--)solve();
    
    return 0;
}

F. Igor and Mountain(前缀dp)

题意:给一个 n ∗ m n*m nm黑白网格。定义合法路径需要满足:只经过黑色格子,起点在最后一行终点在第一行,每行至少经过一个格子至多经过两个格子,路径上相邻两个格子距离不超过 d d d。求合法路径数量。
(搬自洛谷的公式)
在这里插入图片描述
从下往上 d p dp dp d p dp dp的时候维护一下本层的前缀和即可。

#include<bits/stdc++.h>
#define int long long

using namespace std;
typedef long long ll;
using i64 =long long;
using i128 =__int128;
const int N = 2e3+10;
const int mod = 998244353;
int dp[N][N],sum[N][N],g[N][N];
int n,m,x;
int cal(int id,int l,int r){
    l = max(l,1ll),r=min(r,m);
    return (sum[id][r]-sum[id][l-1]+mod)%mod;
}
void solve(){
    cin>>n>>m>>x;
    for(int i=0;i<=n;i++){
        for(int j=0;j<=m;j++){
            dp[i][j]=sum[i][j]=0;
        }
    }
    string s;
    for(int i=1;i<=n;i++){
        cin>>s;
        for(int j=1;j<=m;j++){
            if(s[j-1]=='X')g[i][j]=1;
            else g[i][j]=0;
        }

    }
    for(int i=1;i<=m;i++)if(g[n][i])dp[n][i]=1;
    for(int i=1;i<=m;i++)sum[n][i]=(sum[n][i-1]+dp[n][i])%mod;
    for(int i=1;i<=m;i++)if(g[n][i])dp[n][i]=cal(n,i-x,i+x)%mod;
    for(int i=1;i<=m;i++)sum[n][i]=(sum[n][i-1]+dp[n][i])%mod;

    for(int k=n-1;k>=1;k--){
        for(int i=1;i<=m;i++)if(g[k][i])dp[k][i]=cal(k+1,i-(x-1),i+(x-1))%mod;
        for(int i=1;i<=m;i++)sum[k][i]=(sum[k][i-1]+dp[k][i])%mod;
        for(int i=1;i<=m;i++)if(g[k][i])dp[k][i]=cal(k,i-x,i+x)%mod;
        for(int i=1;i<=m;i++)sum[k][i]=(sum[k][i-1]+dp[k][i])%mod;
    }
    cout<<cal(1,1,m)<<"\n";;
}



int32_t main(){
    ios::sync_with_stdio(false),cin.tie(nullptr);
    int _ = 1;
    cin>>_;
    while(_--)solve();
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值