1、前后缀贪心,比如说观察前后缀的sum,去看以后怎么考虑最好。Problem - 1903C - Codeforces
2、双指针贪心法,考虑两端相消或者相互作用,还有就是考虑左右边界。 Problem - 1891C - Codeforces
Problem - 1907D - Codeforces
3、转换观察法,有些关系可以抽象成图,观察图的某些性质去总结规律。也可以抽象成一个集合,两个集合相等可以说明有解可构造。Problem - 1891C - Codeforces
4、打表找规律,一般没什么规律可循即可打表找规律,一般和数论有关的很喜欢考,acm也喜欢考,属于人类智慧题。Problem - 1916D - Codeforces
5、公式推导演算,常见的分为公式的等价变形、公式的化简(这个常考,一般需要先证明某些性质,可以直接抵消,一般如果原公式处理起来很复杂时就可以考虑)。Problem - 1889B - Codeforces
6、考虑奇偶数去简化问题或者分类问题,从其中的一些运算性质入手,因为奇数偶数的加减以及%运算(这个结论很重要)的结果的奇偶性是固定的,Problem - 1898C - Codeforces
7、根据性质构造模型,看看能不能分成几个块,几个不同的集合,再选择算法去解决。Problem - 1873G - Codeforces
8、考虑从小到大处理,或者是从大到小处理,有时候先处理小的对大的不会有影响,或者反过来,这样的处理顺序是最完美的。Problem - 1904D2 - Codeforces
9、边界贪心法,一般要在问题的最边界处考虑,有时候这样做结果是最优的,或者考虑边界上的影响,假如让影响最小,就使得影响<= 固定值 。 Problem - E - Codeforces and Problem - 1903C - Codeforces
显然,最大值最小值相等时直接输出1,否则直接输出max
#include
#define int long long
using namespace std;
const int N = 2e5 + 10, inf = 0x3f3f3f3f;
int n;
int a[N];
void solve() {
cin >> n;
int mx = -inf, mn = inf, s = 0;
for(int i = 1; i <= n - 1; i ++ )
cin >> a[i], mn = min(mn, a[i]), mx = max(mx, a[i]);
if(mn==mx) {
cout<<1<> T;
while(T --) solve();
return 0;
}
题解:这里我推导一下:
裴属定理:
代码:
#include
#define int long long
using namespace std;
const int N = 2e5 + 10;
int a, b, c, m;
int exgcd(int &x, int &y, int a, int b) {
if(!b) {
x = 1, y = 0;
return a;
}
int d = exgcd(y, x, b, a % b);
y -= x * (a / b);
return d;
}
void solve() {
cin >> a >> b >> c >> m;
int ans = __gcd(__gcd(a, b), c);
if(m % ans) puts("NO");
else puts("YES");
}
signed main() {
int ts;
cin >> ts;
while(ts --) solve();
return 0;
}
贪心思路:
排完序以后一定是最优解,假设排完序以后的状态:
假设a[1] + a[i],a[i] != a[n],那么a[2] + a[i + 1] >= a[1] + a[i],为什么是选a[2]呢,因为往后的大的应该尽量安排到小的a[x]上面,所以这样是会让结果偏大的。
代码:
#include
#define ff first
#define ss second
using namespace std;
using PII = pair;
const int N = 2e5 + 10;
int n, m, b[N];
PII a[N];
void solve() {
cin >> n;
for(int i = 1; i <= n; i ++ ) cin >> a[i].ff, a[i].ss = i;
mapm1;
mapm2;
for(int i = 1; i <= n; i ++ ) {
m1[a[i]] = i;
m2[i] = a[i];
}
sort(a + 1, a + 1 + n);
int l = 1, r = n;
int x = a[l].ff + a[r].ff;
bool flag = 1;
while(l < r) {
if(a[l].ff + a[r].ff != x) {
flag = 0;
break;
}
l ++, r --;
}
if(n % 2 && 2 * a[n / 2 + 1].ff != x) flag = 0;
if(!flag) {
cout << "NO" << endl;
return;
}
cout << "YES" << endl;
vector rs;
for(int i = 1; i <= n; i ++ ) {
if(m2[i] == a[i]) continue;
PII t = a[i], t_ = m2[i];
int pos = m1[t];
m1[t_] = pos, m1[t] = i;
m2[pos] = t_, m2[i] = t;
rs.push_back({i,pos});
}
cout << rs.size() << endl;
for(auto t : rs)
cout << t.ff << ' ' << t.ss << endl;
}
int main() {
int T;
cin >> T;
while(T --) solve();
return 0;
}