Round 1013(Div.3)
D. Place of the Olympiad
题意:给一个 n ∗ m n*m n∗m 的网格黑白染色,使得恰好有 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=p∗b 的个数,其中
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
n∗m黑白网格。定义合法路径需要满足:只经过黑色格子,起点在最后一行终点在第一行,每行至少经过一个格子至多经过两个格子,路径上相邻两个格子距离不超过
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;
}
881

被折叠的 条评论
为什么被折叠?



