完全数
- 完全数满足:一个数的所有因子之和 - 它自己 = 它自己
- 因子之和 = 约数之和
- 求一个数的所有约数之和:
先把每个质因数从0次幂一直加到其最高次幂,再把每个相应质因数幂的和相乘.
代码如下:
#include<bits/stdc++.h> using namespace std; #define mm(a,x) memset(a,x,sizeof a) #define mk make_pair #define ll long long #define pii pair<int,int> #define inf 0x3f3f3f3f #define lowbit(x) (x) & (-x) #define endl "\n" ll n; unordered_map<int,int > primes; ll ans = 1; void divide(ll n){ for(ll i = 2; i <= n/i; i ++ ){ while(n % i == 0){ n/=i; primes[i] ++; } } if(n > 1) primes[n] ++; } int main() { cin >> n; divide(n); for(auto prime:primes){ ll p = prime.first,a = prime.second; ll t = 1; while(a -- ) t = t * p + 1; ans *= t; } if(ans - n == n) cout<<"Pure"; else if(ans - n > n) cout<<"Late"; else cout<<"Early"; return 0; }
移动撤销
- 利用栈来存放上一次操作
- 若栈不为空,就可以撤销
代码如下:
#include<bits/stdc++.h> using namespace std; #define mm(a,x) memset(a,x,sizeof a) #define mk make_pair #define ll long long #define pii pair<int,int> #define inf 0x3f3f3f3f #define lowbit(x) (x) & (-x) #define endl "\n" const int N = 1e5 + 10; int n; string s; int x,y; int stk[N],tt; int main() { cin >> n >> s; int len = s.size(); for(int i = 0; i < len; i ++ ){ if(s[i] == 'W') y ++,stk[++ tt] = 1; if(s[i] == 'A') x --,stk[++ tt] = 2; if(s[i] == 'S') y --,stk[++ tt] = 3; if(s[i] == 'D') x ++,stk[++ tt] = 4; if(s[i] == 'Z'){ int t = 0; if(tt) t = stk[tt --]; if(t == 1) y --; if(t == 2) x ++; if(t == 3) y ++; if(t == 4) x --; } } cout<<x<<" "<<y; return 0; }
石头剪刀布
贪心策略:先把所有可能胜出的情况进行枚举,然后考虑平局的情况
代码如下:
#include<bits/stdc++.h> using namespace std; #define mm(a,x) memset(a,x,sizeof a) #define mk make_pair #define ll long long #define pii pair<int,int> #define inf 0x3f3f3f3f #define lowbit(x) (x) & (-x) #define endl "\n" const int N = 10; int n; ll a[N],b[N]; ll ans; //每局胜者得2分,平局双方各得1分,败者不得分 int main() { cin >> n; for(int i = 0; i < 3; i ++ ){ cin >> a[i]; } for(int i = 0; i < 3; i ++ ){ cin >> b[i]; } ll x = 0; x = min(a[0],b[1]); ans += x * 2; a[0] -= x; b[1] -= x; x = min(a[1],b[2]); ans += x * 2; a[1] -= x; b[2] -= x; x = min(a[2],b[0]); ans += x * 2; a[2] -= x; b[0] -= x; ans += min(a[0],b[0]); ans += min(a[1],b[1]); ans += min(a[2],b[2]); cout<<ans; return 0; }
夹缝中求和
- n的范围在[2,1e5],时间复杂度O(n)或者O(nlogn)
- 选取一个数ai,另一个数一定在[x - ai,y - ai]之间
- 先进行排序,再进行二分查找不小于当前值作为左端点l,大于当前值作为右端点r
- 符合答案的区间为r - l.
代码如下:
#include<bits/stdc++.h> using namespace std; #define mm(a,x) memset(a,x,sizeof a) #define mk make_pair #define ll long long #define pii pair<int,int> #define inf 0x3f3f3f3f #define lowbit(x) (x) & (-x) #define endl "\n" const int N = 1e5 + 10; ll n,x,y; ll a[N]; int l,r; ll ans; int main() { cin >> n >> x >> y; for(int i = 1; i <= n; i ++ ) cin >> a[i]; sort(a + 1, a + n + 1); for(int i = 1; i <= n; i ++ ){ l = lower_bound(a + i + 1,a + n + 1,x - a[i]) - a; r = upper_bound(a + i + 1,a + n + 1,y - a[i]) - a; ans += (r - l); } cout<<ans; return 0; }