Codeforces Round 988 (Div. 3)
Codeforces Round 988 (Div. 3) 总结
A
没啥好说的,用桶存出现次数。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int N=25;
int n;
int a[N],c[N];
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],c[a[i]]++;
int ans=0;
for(int i=1;i<=n;i++)
{
ans+=c[i]/2;
c[i]=0;
}
cout<<ans<<'\n';
}
int main ()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--) solve();
return 0;
}
B
依据题意有
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int k;
int a[N],c[N];
void solve()
{
cin>>k;
for(int i=1;i<=k;i++) cin>>a[i],c[i]=0;
for(int i=1;i<=k;i++) c[a[i]]++;
int x=k-2;
for(int i=1;1ll*i*i<=x;i++)
if(x%i==0&&c[i]&&c[x/i])
{
cout<<i<<' '<<x/i<<'\n';
return ;
}
}
int main ()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--) solve();
return 0;
}
C
首先容易想到,奇数相加可行,偶数相加可行,而最小的奇合数为
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n;
int a[N];
void solve()
{
cin>>n;
if(n<=4)
{
cout<<-1<<'\n';
return ;
}
int cnt=0;
for(int i=7;i<=n;i+=2) cout<<i<<' ';
cout<<"1 3 5 4 2 ";
for(int i=6;i<=n;i+=2) cout<<i<<' ';
cout<<'\n';
}
int main ()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--) solve();
return 0;
}
D
考虑贪心,首先能不捡就不捡,遇到障碍跳不过去时,才返回去捡加速器,要求捡的次数最小,所以回去捡的加速器要先捡大的。
因此枚举障碍
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,m,L;
int l[N],r[N];
int x[N],v[N];
priority_queue<int> q;
void solve()
{
cin>>n>>m>>L;
for(int i=1;i<=n;i++) cin>>l[i]>>r[i];
for(int i=1;i<=m;i++) cin>>x[i]>>v[i];
int k=1,id=1,ans=0;
for(int i=1;i<=n;i++)
{
int len=r[i]-l[i]+2;
while(x[id]<l[i]&&id<=m) q.push(v[id]),id++;
while(q.size()&&k<len) k+=q.top(),ans++,q.pop();
if(k<len)
{
cout<<-1<<'\n';
return ;
}
}
while(q.size()) q.pop();
cout<<ans<<'\n';
}
int main ()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--) solve();
return 0;
}
E
交互题,记得用 endl
或者 cout.flush()
清空缓存区。
询问次数最大为
先考虑无解的情况,显然是
然后遍历
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int N=1e4+5;
int n;
int s[N];
int query(int l,int r)
{
int x;
cout<<"? "<<l<<" "<<r<<' '<<endl;
cin>>x;
return x;
}
int k[N];
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) s[i]=0;
for(int i=2;i<=n;i++) k[i]=query(1,i);
if(k[n]==0)
{
cout<<"! IMPOSSIBLE "<<endl;
return ;
}
for(int i=2;i<=n;i++) if(k[i]>k[i-1]) s[i]=1;
for(int i=2;i<=n;i++)
if(s[i])
{
for(int j=1;j<=i-1-k[i];j++) s[j]=1;
break;
}
cout<<"! ";
for(int i=1;i<=n;i++) cout<<s[i];
cout<<' '<<endl;
}
int main ()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--) solve();
return 0;
}
F
二分答案,设攻击了
因为只能是在同一个位置
这样就转化成了
离散化加差分轻松搞定,复杂度为
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int N=2e5+5,inf=1e9;
int n,m,k;
int h[N],x[N],t[N];
int tot;
int b[N],c[N];
bool check(int k)
{
tot=0;
for(int i=1;i<=n;i++)
{
t[i]=(h[i]+k-1)/k;
if(t[i]<=m)
{
c[++tot]=x[i]-(m-t[i]);
c[++tot]=x[i]+(m-t[i])+1;
}
}
sort(c+1,c+tot+1);
tot=unique(c+1,c+tot+1)-c-1;
for(int i=1;i<=tot;i++) b[i]=0;
for(int i=1;i<=n;i++)
{
if(t[i]<=m)
{
int l=lower_bound(c+1,c+tot+1,x[i]-(m-t[i]))-c;
int r=lower_bound(c+1,c+tot+1,x[i]+(m-t[i])+1)-c;
b[l]++,b[r]--;
}
}
for(int i=1;i<=tot;i++) b[i]+=b[i-1];
for(int i=1;i<=tot;i++) if(b[i]>=k) return 1;
return 0;
}
void solve()
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++) cin>>h[i];
for(int i=1;i<=n;i++) cin>>x[i];
int l=1,r=inf,mid,ans=-1;
while(l<=r)
{
mid=l+r>>1;
if(check(mid)) r=mid-1,ans=mid;
else l=mid+1;
}
cout<<ans<<'\n';
}
int main ()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
while(T--) solve();
return 0;
}
G
dp 加容斥。
逐步推导,设
这样做是
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
const int N=2e5+5,mod=998244353,M=1e6+5;
int n;
int a[N];
int f[N];
int gcd(int x,int y)
{
return y ? gcd(y,x%y) : x;
}
vector<int> g[M],h[N];
set<int> v;
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
f[1]=1;
for(int i=2;i<=n;i++)
for(int j=1;j<=i-1;j++)
if(gcd(a[i],a[j])!=1)
f[i]=(f[i]+f[j])%mod;
cout<<f[n]<<'\n';
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
solve();
return 0;
}
考虑优化,不难发现我们其实并不在意具体的
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
const int N=2e5+5,mod=998244353,M=1e6+5;
int n;
int a[N],f[N];
vector<int> g[M],h[N];
set<int> v;
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int x=a[1];
for(int j=2;1ll*j*j<=n;j++)
{
if(x%j==0)
{
g[j].push_back(1);
while(x%j==0) x/=j;
}
}
if(x>1) g[x].push_back(1);
f[1]=1;
for(int i=2;i<=n;i++)
{
int x=a[i];
for(int j=2;1ll*j*j<=x;j++)
{
if(x%j==0)
{
for(int k:g[j])
{
if(v.count(k)==0) f[i]=(f[i]+f[k])%mod;
v.insert(k);
}
g[j].push_back(i);
while(x%j==0) x/=j;
}
}
if(x>1)
{
for(int k:g[x])
{
if(v.count(k)==0) f[i]=(f[i]+f[k])%mod;
v.insert(k);
}
g[x].push_back(i);
}
v.clear();
}
cout<<f[n]<<'\n';
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
solve();
return 0;
}
但这样还是过不了。因为这最坏还是
然后不妨按质因数划分集合,设
考虑这样一组数据
这里就是
如何避免这样情况呢?用容斥原理。
将 g[a[i]]
中。比如 g[12]={2,3,6}
,这时候可以计算上面例子,
也就是说在每次更新 g[a[i]]
中的每个元素 g[a[i]]
中的每个元素
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int N=2e5+5,M=1e6+5,mod=998244353;
int n;
int a[N],b[M],f[N];
vector<int> g[M],h[M];
void divide1(int x,int id)
{
for(int i=2;1ll*i*i<=x;i++)
{
if(x%i==0)
{
h[id].push_back(i);
while(x%i==0) x/=i;
}
}
if(x>1) h[id].push_back(x);
}
void divide2(int x,int id)
{
x=1;
for(auto t:h[id]) x*=t;
for(int i=2;1ll*i*i<=x;i++)
{
if(x%i==0)
{
g[id].push_back(i);
if(x!=i) g[id].push_back(x/i);
}
}
if(x>1) g[id].push_back(x);
}
void solve()
{
cin>>n;
int mx=0;
for(int i=1;i<=n;i++) cin>>a[i],mx=max(mx,a[i]);
for(int i=2;i<=mx;i++) divide1(i,i),divide2(i,i);
f[1]=1;
for(int i=1;i<=n;i++)
{
for(auto x:g[a[i]])
{
if(h[x].size()&1) f[i]=(f[i]+b[x])%mod;
else f[i]=(f[i]+mod-b[x])%mod;
}
for(auto x:g[a[i]]) b[x]=(b[x]+f[i])%mod;
}
cout<<f[n]<<'\n';
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)