1463.B. Find The Array(构造,思维)
题意:
给出数列a,其总和为S。
要构造一个数列b,满足其相邻两项可以相互整除,并且|ai-bi|
之和不超过S/2
。
思路:
两种思路。
思路1:
设a数列的奇数位置之和为S奇,偶数位置之和为S偶。那么,S奇+S偶=S。
同时,满足S奇和S偶中,至少有一个不超过S/2。(反证,如果都超过了,那么两者之和就超过S了)
我们把数列b中,这种位置 (奇数或偶数位置)上的所有数构造为1,其他位置构造为ai。
首先,满足了相邻位置两项可以互相整除。
其次,这种位置(奇/偶 位置)的|ai-bi|
之和不超过S/2,另一种位置的|ai-bi|
之和为0。总和不超过S/2。
思路2:
将b数列的每个数bi,构造为不超过对应位置ai的,2的最高次幂数。
这样,每个位置的|ai-bi|
的值不超过ai的一半,那么所有位置|ai-bi|
的总和也就不超过S/2。
Code:
const int N = 200010, mod = 1e9+7;
int T, n, m, a[N];
//思路2:
int main(){
Ios;
cin>>T;
while(T--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
int x;cin>>x;
int p=log(x)/log(2);
cout<<(ll)pow(2,p)<<" ";
}
cout<<endl;
}
return 0;
}
//思路1:
int main(){
Ios;
cin>>T;
while(T--)
{
cin>>n;
ll sum1=0,sum2=0,sum=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(i%2) sum1+=a[i];
else sum2+=a[i];
sum+=a[i];
}
if(sum2<=sum/2)
{
for(int i=1;i<=n;i++)
{
if(i%2) cout<<a[i]<<" ";
else cout<<1<<" ";
}
}
else
{
for(int i=1;i<=n;i++)
{
if(i%2) cout<<1<<" ";
else cout<<a[i]<<" ";
}
}
cout<<endl;
}
return 0;
}
经验:
以后碰见互相整除问题要向2的幂次数上想。对于任意两个2的幂次数,都是可以相互整除的。
1和其他任意数也是可以的。
另外就是:S奇和S偶,至少有一个是不超过S/2的。
1303B. National Project(二分答案)
题意:
有一个长度为n公里的公路要施工,每天施工1公里。
有两种天气,好天气 x天 和 坏天气 y天,轮流出现。这n公里的施工要保证好天气的天数不少于一半。
问,施工完成最少需要多少时间?
思路:
对于最少时间不好求,但是对于给定的时间,可以判断其是否满足。
判断给定x天是否满足:当前x天中好天气的天数+能用的坏天气天数 是否超过n。
所以就可以二分答案。
能用的坏天气天数为:min(总共的坏天气天数,n/2)。
Code:
const int N = 200010, mod = 1e9+7;
int T, n, m, a[N];
int x,y;
bool check(int mid)
{
int q=mid/(x+y);
int left=mid%(x+y);
int t=q*x+min(left,x);
int t1=min(n/2,q*y+max(0ll,left-x));
return t+t1>=n;
}
signed main(){
Ios;
cin>>T;
while(T--)
{
cin>>n>>x>>y;
int l=n,r=1e18;
while(l<r)
{
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<l<<endl;
}
return 0;
}
经验:
原本以为二分答案已经掌握的很好了,但是见到这个题还是没想起来二分。。
以后要思维发散些,做不出来的时候想想这些算法能不能用。
977D. Divide by three, multiply by two(map+暴搜)
题意:
给出一个长度为n的数列a,输出满足下列要求的再排列。(n≤100)
要求:后一个数为前一个数除3 或 前一个数的2倍。
思路:
map记录下每个数是否存在。
暴搜即可。
Code:
const int N = 200010, mod = 1e9+7;
ll T, n, m, a[N];
ll f[N];
void dfs(int u)
{
if(u==n+1){
for(int i=1;i<=n;i++) cout<<f[i]<<" ";
return;
}
if(f[u-1]%3==0&&mp[f[u-1]/3]){
f[u]=f[u-1]/3;
dfs(u+1);
}
if(mp[f[u-1]*2]){
f[u]=f[u-1]*2;
dfs(u+1);
}
}
int main(){
Ios;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],mp[a[i]]++;
for(int i=1;i<=n;i++)
{
f[1]=a[i];
dfs(2);
}
return 0;
}
挺好。