洛谷 P2678 题目链接:点击这里传送
思路:
对最短距离的最大值进行二分答案,具体看代码注释
#include<bits/stdc++.h>
using namespace std;
long long maxl, n, m, ans;//距离,岩石数,至多移走的岩石数
long long a[500005];//记录n块岩石与起点的距离
bool flag(long long dis)
{
long long step = 0;
long long f = 0;
for (long long i = 1; i <= n + 1; i++)
{
if (dis > (a[i] - a[f]))//假设最短距离为dis,出现了比dis还短的距离,那把这块石头移走
{
step++;
f = f;
}
else { f = i; }
}
return m >= step;
}
int main()
{
cin >> maxl >> n >> m;
for (long long i = 1; i <= n; i++)
{
cin >> a[i];
}
a[n + 1] = maxl;
long long l = 1, r = maxl;//对最短距离的最大值进行二分答案
while (l <= r)
{
long long mid = (l + r) / 2;
if (flag(mid))//还可以继续增大最短距离
{
ans = mid;
l = mid + 1;
}
else { r = mid - 1; }
}
cout << ans;
return 0;
}
Codeforces 1541A 题目链接:点击这里传送
题意:
给出一个全排列,你可以让某一个元素左移或右移。最少要几次这样的操作能使所有的元素都不在他们的初始位置上。
思路:
偶数两两交换,奇数n-3再两两交换。
#include<bits/stdc++.h>
using namespace std;
int n, t;
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> t;
while (t--)
{
cin >> n;
if (n % 2 == 0)
{
for (int i = 1; i <= n / 2; i++)
{
cout << 2 * i << " " << 2 * i-1 <<" ";
}
cout << endl;
}
else
{
cout << "3 1 2 ";
if (n == 3) continue;
for (int i = 1; i <= (n - 3) / 2; i++)
{
cout << 2 * (i + 1) + 1 << " " << 2 * (i + 1)<<" ";
}
cout << endl;
}
}
return 0;
}
Codeforces 1542B 题目链接:点击这里传送
题意:
1存在于这个集合。
这个集合的元素
×
\times
×a存在于这个集合,这个集合的元素+b存在于这个元素。
现给出n,问n是否存在于这个元素。
思路:
存在于集合中的元素都满足这样的条件:由两部分的和组成,第一部分是
a
k
a^k
ak,第二部分能被b整除。
#include<bits/stdc++.h>
using namespace std;
long long t,n,a,b;
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>t;
while(t--)
{
cin>>n>>a>>b;
int f=0;
if(a==1)
{
if(b==1)
{
cout<<"YES"<<endl;
continue;
}
if(n%b==1) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
continue;
}
for(long long i=1;i<=n;i*=a)
{
if((n-i)%b==0)
{
f=1;
break;
}
}
if(f==0) cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
return 0;
}
Codeforces 1542C 题目链接:点击这里传送
题意:
f(n)是最小的不是n的因数的数字。求f(1)+f(2)+…+f(n)
思路:
算贡献。n/lcm(1,2,3,…,m-1)是因子不含m的个数,n/lcm(1,2,3,…,m)是因子不含m+1的个数,减一下就是f(x)=m的个数,再乘m就是m的贡献值。把1~n都这样算一下累加起来就是答案。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAX_TEMP 44
#define mod 1000000007
ll gcd(ll a,ll b)
{
if(a<b) swap(a,b);
while(b)
{
ll temp=a%b;
a=b;
b=temp;
}
return a;
}
ll lcm(ll a,ll b)
{
return a*b/gcd(a,b);
}
ll t,n,ans;
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>t;
while(t--)
{
cin>>n;
ll temp1=1;//大的
ll temp2=1;//小的
ll ans=0;
for(ll i=2;i<=MAX_TEMP;i++)// i*(n/lcm(1,2...i-1)-n/(lcm(1,2...i)))
{
temp1=lcm(temp1,i-1);
temp2=lcm(temp2,i);
if(n/temp1==0) break;
ans=ans+i*(n/temp1-n/temp2);
}
cout<<ans%mod<<endl;
}
return 0;
}
Codeforces 1543A 题目链接:点击这里传送
题意:
给出两个数,你可以使他们共同变大或变小。求他们gcd的最大值。
思路:
差值是他们最大的gcd。变大变小算一下比较最小值。
#include<bits/stdc++.h>
using namespace std;
long long t,a,b;
#define ll long long
ll solve(ll x,ll y)
{
for(int i=1;;i++)
{
ll temp=y*i;
if(temp>=x) return temp;
}
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>t;
while(t--)
{
cin>>a>>b;
if(a==b)
{
cout<<"0 0"<<endl;
continue;
}
ll mini=min(a,b);
ll maxi=max(a,b);
cout<<maxi-mini<<" ";
ll maxn=solve(mini,maxi-mini);
cout<<min(maxn-mini,mini%(maxi-mini))<<endl;
}
return 0;
}
Codeforces 1542A 题目链接:点击这里传送
题意:
任意选两个数组成一对,n对下来后每对的和要求为奇数。
思路:
统计奇数和偶数的个数,相同就输出YES,否则输出NO
#include<bits/stdc++.h>
using namespace std;
int t, n;
#define MAXN 200005
int a[MAXN];
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> t;
while (t--)
{
cin >> n; for (int i = 1; i <= 2*n; i++) cin >> a[i];
int cnt1 = 0; int cnt2 = 0;
for (int i = 1; i <= 2 * n; i++)
{
if (a[i] % 2) cnt1++;
else cnt2++;
}
if (cnt1 == cnt2) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
Codeforces 1557A 题目链接:点击这里传送
题意:
将一个序列分成两部分,使这两部分的平均数的和最大。
思路:
最大的单独拿出来。试想,如果拿两个最大的,两个部分的平均值都会变小,再拿下去更小,很容易证明这样贪心最优。
#include<bits/stdc++.h>
using namespace std;
double maxn, sum, temp;
int t,n;
int main()
{
cin >> t;
while (t--)
{
sum = 0;
maxn = -999999999;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
scanf("%lf", &temp);
maxn = max(maxn, temp);
sum += temp;
}
printf("%.6lf\n", (sum - maxn) / (n - 1) + 0.0 + maxn * 1.0);
}
return 0;
}
Codeforces 1557B 题目链接:点击这里传送
题意:
每次将一个序列最多分成k部分,这k个整体可以任意调换位置。问能否整体实现升序。
思路:
排序后标记好各自排序后的位置。再对原数组那些不满足a[i+1].id-1=a[i].id的情况计数。因为这种时候就需要分开来排序。当计数个数大于k是,就不成立。
#include<bits/stdc++.h>
using namespace std;
int t, n,k;
#define MAXN 100005
struct node {
int id;
int val;
}a[MAXN];
bool cmp(node a, node b) { return a.val < b.val; }
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> t;
while (t--)
{
cin >> n>>k;
for (int i = 1; i <= n; i++)
{
cin >> a[i].val;
a[i].id = i;
}
sort(a + 1, a + 1 + n, cmp);
int cnt = 1;
for (int i = 1; i < n; i++)
{
if (a[i + 1].id - a[i].id != 1) cnt++;
}
if (cnt > k) cout << "NO" << endl;
else cout << "YES" << endl;
}
return 0;
}