思路:
容易发现这个题要求的就是它的所有因子之和,所以
唯一分解定理
就可以用一个比较不错的复杂度切掉这题。
代码:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long int ll;
ll dcpSum(ll x){//所有因子的和(包括1)
ll ans = 1;
for(ll i = 2; i * i <= x; i++){
if(x % i == 0){
ll temp = 1;
while(x % i == 0){
x /= i;
temp *= i;
}
ans *= (temp * i - 1) / (i - 1);//对每一个素数因子按图一公式求积。
}
}
if(x > 1) ans *= (1 + x);
return ans;
}
void solved(){
ll n;scanf("%lld",&n);
ll s = dcpSum(n) - n;
/*
ll s = 0;
for(int i = 1; i * i <= n; i++){
if(n % i == 0){
s += i;
if(i * i != n && i != 1){
s += (n / i);
}
}
}
*/
if(s == n){
cout << "Pure" << endl;
}else if(s > n){
cout << "Late" << endl;
}else{
cout << "Early" << endl;
}
}
int main(){
solved();
return 0;
}
思路:
模拟就行了
由于会回溯到某个位置,所以用一个数组记录每一步就行了。
代码:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 2e5 + 10;
char s[maxn];
pair<int,int>ve[maxn];
void solved(){
int n;scanf("%d",&n);
scanf("%s",s + 1);
int cur = 0;
ve[cur] = {0,0};
for(int i = 1; i <= n; i++){
int x = ve[cur].first;
int y = ve[cur].second;
if(s[i] == 'W'){
ve[++cur] = {x,y + 1};
}
if(s[i] == 'A'){
ve[++cur] = {x - 1,y};
}
if(s[i] == 'S'){
ve[++cur] = {x,y - 1};
}
if(s[i] == 'D'){
ve[++cur] = {x + 1,y};
}
if(s[i] == 'Z'){
cur--;
cur = max(0,cur);
}
}
cout << ve[cur].first << ' ' << ve[cur].second << endl;
}
int main(){
solved();
return 0;
}
思路:
贪心:先把石头对剪刀,剪刀对布,布对石头,这样可以赢得到的分数是(min(a1,b2) + min(b1,c2) + min(c1,c2))*2
然后把用掉的全部剪掉,然后再取平局就好了。
代码:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long int ll;
void solved(){
ll a1,b1,c1,a2,b2,c2;
ll n;cin >> n;
cin >> a1 >> b1 >> c1;
cin >> a2 >> b2 >> c2;
ll t1 = min(a1,b2);
ll t2 = min(b1,c2);
ll t3 = min(c1,a2);
ll s = t1 * 2 + t2 * 2 + t3 * 2;
a1 -= t1;b2 -= t1;
b1 -= t2;c2 -= t2;
c1 -= t3;a2 -= t3;
s += min(a1,a2) + min(b1,b2) + min(c1,c2);
cout << s << endl;
}
int main(){
solved();
return 0;
}
这题我题意理解错了,导致在错误的道路上越走越远,这题其实很简单。。。
我一开始看到这个题想到的是权值线段树,不过值域太大了,又离散化不了。就换其它方向,后面想,先对所有数排序,然后枚举每个数,二分出它的[l - x,r - x]的区间,然后求这个区间<=这个数在原序列的index的数量,这就转化为区间<=x数量问题了,可以考虑主席树搞。。。。最后没搞出来。。。我错就错在i<j这个条件没理解清楚。
其实这个题目就是要我们求任意两个数的和在[l,r]有多少个。
那么只需要排序,然后对每个数二分一下它的可以选的区间累和就完了。。。。害。。。一直卡在i<j上面了,其实换个题意就直接秒了。。。。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long int ll;
const int maxn = 2e5 + 10;
ll n,x,y;
ll a[maxn];
void solved(){
cin >> n >> x >> y;
for(int i = 1; i <= n; i++)cin >> a[i];
sort(a + 1,a + 1 + n);
ll ans = 0;
for(int i = 1; i <= n; i++){
int l = lower_bound(a + 1 + i,a + n + 1,x- a[i]) - (a);
int r = upper_bound(a + 1 + i,a + n + 1,y - a[i]) - (a);
ans += (r - l);
}
cout << ans <<endl;
}
int main(){
solved();
return 0;
}
京公网安备 11010502036488号