P11312 神奇的小江鸟
P11312 神奇的小江鸟
心路历程
赛时我连绿都切不了,我是fw。
赛时重要性质都推出来了,但是算错时间复杂度,导致只打了个简单的暴力,赛后才改对。
思路
首先我们需要知道两个个重要的性质:
- 当确定了最终的 \(\gcd\) 出来的值 \(ans\) 可以 \(O(n)\) 检测并输出(
r[i]/ans*ans)。 - 当所有的区间范围都大于 \(k\) 的时候,是可以直接令所有数 \(\gcd\) 等于 \(k\) 的。
确定了这两个性质,我们就可以把最小的区间里的可选的数的因数枚举出来然后用第一个性质来算一遍输出就行了。
ACcode
#include <bits/stdc++.h>
using namespace std;
#define freop(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);
#define int long long
#define double long double
#define re register
#define endl '\n'
#define inf 0x7f7f7f7f7f7f7f7f
#define lowbit(x) (x&-x)
#define pii pair<int,int>
#define fir first
#define sec second
#define umap unordered_map
#define uset unordered_set
const int N=1e4+1;
int T,n,k,mn,mni,l[N],r[N];
set<int> se;//set去重
inline void js(int x){//统计这个数的因数
for(int i = 1;i*i<=x;++i){
if(!(x%i)){
se.insert(i);
if((i*i)^x) se.insert(x/i);
}
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// freop();
//↑以上为初始化↑
//------------------------------
cin >> T;
while(T--){
cin >> n >> k,mni=0;//多测不清空,亲人两行泪
for(int i = 1;i<=n;++i){
cin >> l[i] >> r[i];
if(r[mni]-l[mni]>r[i]-l[i]||!mni) mni=i;//求最小的区间
}
if(k==1||r[mni]-l[mni]+1>=k){//当特殊点或所有区间的长度都大于k
cout << "Yes\n";
for(int i = 1;i<=n;++i) cout << r[i]/k*k << ' ';
cout << endl;
}else{
se.clear();//多测不清空,亲人两行泪
for(int i = l[mni];i<=r[mni];++i) js(i);
bool f=0,fl;
for(int t:se){
if(t<k) continue;
fl=1;
for(int i = 1;i<=n;++i) if(r[i]/t*t<l[i]){fl=0;break;}//看有没有t的倍数在区间内
if(fl){
cout << "Yes\n";
for(int i = 1;i<=n;++i) cout << r[i]/t*t << ' ';//r[i]内t最大的倍数
cout << endl;
f=1;
break;
}
}
if(!f) cout << "No\n";
}
}
return 0;
}

浙公网安备 33010602011771号