T1 勾股数
因为a2=c2−b2,所以可以用平方差公式展开,a2=(c−b)(c+b)
分情况考虑:
当输入的a为奇数时,
令c−b=1,则c+b=a2,所以2b+1=a2,解得:
{b=a2−12c=a2−12+1
当输入的a为偶数时
令c−b=2,则c+b=a22,所以2b+2=a22,解得:
⎧⎩⎨⎪⎪⎪⎪b=a24−1c=a24+1
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int main(){
ll a;
cin >> a;
if(a<=2) cout << "-1";
else if(a&1) cout << (a*a-1)/2 << " " << ((a*a-1)/2)+1;
else cout << (a*a)/4-1 << " " << ((a*a)/4)+1;
return 0;
}
T2 区间和
先将原问题转化为b序列前
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
ll n, m, val, num;
ll a1[100010], sum[100010], summ[100010];
void check(ll x){
ll p = 0;
for(ll i = 1; i <= n; i ++){
p = max(p, i-1);
while(p+1 <= n && sum[p+1] - sum[i-1] <= x) p ++;
val += (summ[p] - summ[i-1] - (p-i+1)*sum[i-1]);
num += (p-i+1);
}
}
ll solve(ll x){
ll l = 0, r = 1e7, ans = 0, res = 0, cnt = 0;
while(l <= r){
ll mid = (l+r) >> 1;
val = 0, num = 0, check(mid);
if(num >= x) r = mid - 1, ans = mid, res = val, cnt = num;
else l = mid + 1;
}
return res - (cnt-x) * ans;
}
int main(){
freopen("sum.in", "r", stdin);
freopen("sum.out", "w", stdout);
scanf("%lld%lld", &n, &m);
for(ll i = 1; i <= n; i ++) scanf("%lld", &a1[i]);
for(ll i = 1; i <= n; i ++) sum[i] = sum[i-1] + a1[i], summ[i] = summ[i-1] + sum[i];
for(ll i = 1; i <= m; i ++){
ll a, b;
scanf("%lld%lld", &a, &b);
printf("%lld\n", solve(b) - solve(a-1));
}
return 0;
}
T3 最长上升子序列
0可以转化成任意整数,包括负数,显然求LIS时尽量把0都放进去必定是正确的。因此我们可以把0拿出来,对剩下的做O(nlogn)的LIS,统计结果的时候再算上0的数量。为了保证严格递增,我们可以将每个权值a[i]减去i前面0的个数,再做LIS,就能保证结果是严格递增的。
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int inf = 1e9;
int f[100010], d[100010], a1[100010];
int n, cnt, ans;
inline int read(){
char c;
int ok = 0, num = 0;
while(c = getchar()){
if(c <= '9' && c >= '0')
ok = 1, num = num*10+c-'0';
else if(ok) return num;
}
}
inline int find(int l, int r, int val){
int ans1 = 0;
while(l <= r){
int mid = (l+r)>>1;
if(d[mid] >= val) r = mid-1;
else ans1 = mid,l = mid+1;
}
return ans1;
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i ++) d[i] = inf; d[0] = -inf;
for(int i = 1; i <= n; i ++) a1[i] = read();
for(int i = 1; i <= n; i ++){
if(a1[i] == 0){
d[ans+1] = d[ans]+1;
for(int j = ans; j >= 1; j --)
if(d[j] > d[j-1]+1)
d[j] = d[j-1]+1;
f[i] = ++ ans;
continue;
}
f[i] = find(0,i-1,a1[i])+1;
if(a1[i] < d[f[i]]) d[f[i]] = a1[i];
if(f[i] > ans) ans = f[i];
}
printf("%d", ans);
return 0;
}