For a positive integer n let's define a function f:
f(n) = - 1 + 2 - 3 + .. + ( - 1)nn
Your task is to calculate f(n) for a given integer n.
The single line contains the positive integer n (1 ≤ n ≤ 1015).
Print f(n) in a single line.
4
2
5
-3
f(4) = - 1 + 2 - 3 + 4 = 2
f(5) = - 1 + 2 - 3 + 4 - 5 = - 3
水题,找规律或推出公式,如果n是偶数答案是n/2,否则答案是-(n+1)/2
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#define mem(x) memset(x, 0, sizeof(x))
using namespace std;
const int N = 1010;
typedef __int64 ll;
int main(){
ll n;
cin >> n;
if(n & 1) cout << -(n+1)/2<<endl;
else cout << n/2 << endl;
return 0;
}
给出一个矩阵B,问能否构造出矩阵A使得矩阵A 中第i行第j列的值取或后得到Bij的值
如果Bij的值为0,很显然矩阵A中第i行第j列的所有值均要为0,因此我们可以先根据Bij中为0的值构建一个矩阵A,其余值
设为1,再判断这个矩阵A是否满足题意
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#define mem(x) memset(x, 0, sizeof(x))
using namespace std;
const int N = 110;
typedef __int64 ll;
int mp[N][N], res[N][N];
int a[N], b[N];
int n, m;
int main(){
while(cin >> n >> m){
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j) cin >> mp[i][j], a[i] = b[j] = 1;
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= m; ++j){
if(!mp[i][j]) a[i] = b[j] = 0;
}
}
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j){
if(!(a[i] & b[j])) res[i][j] = 0;
else res[i][j] = 1;
}
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= m; ++j){
if(res[i][j]) a[i] = b[j] = 1;
}
}
//for(int i = 1; i <= n; ++i) cout << a[i] << " "; cout << endl;
//for(int j = 1; j <= m; ++j) cout << b[j] << " "; cout << endl;
int flag = 1;
for(int i = 1; i <= n && flag; ++i){
for(int j = 1; j <= m && flag; ++j){
if(mp[i][j]){
if(!(a[i] | b[j])) flag = 0;
}
}
}
if(flag){
puts("YES");
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= m; ++j) cout << res[i][j] << " ";
cout << endl;
}
}
else puts("NO");
}
return 0;
}
题意:给一个长度为n的串和光标的位置p,有四种操作,1.向左移动光标,2.向右移动,每步只能移动一位,可将串看做环,3.改变光标所指的字符,每步只能改为相邻字符,也是环形,如Hint所示,求最少几步构造出回文串
解题思路:易知回文串是确定的,故只需对一半串进行操作,而光标也只用在考虑一侧的情况,先求出哪些位置需要修改,需要修改几步,再计算移动的步数,移动的最少步数为两端距当前光标点远一端的一倍+近端的二倍
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#define mem(x) memset(x, 0, sizeof(x))
using namespace std;
const int N = 100010;
typedef __int64 ll;
char str[N];
int n, pos;
int c[N];
int mdf[N];
int main(){
cin >> n >> pos;
cin >> str + 1;
if(pos > (n + 1) / 2) pos = n - pos + 1;
int num = 0, res = 0;
for (int i = 1; i <= (n + 1) / 2; ++i){
char t1 = str[i], t2 = str[n - i + 1];
if (t1 > t2) swap(t1, t2);
if (t1 != t2){
mdf[num++] = i;
res += min(t2 - t1, t1 - t2 + 26);
}
}
//cout << "res = " << res << endl;
if (res == 0){
cout << 0 << endl;
return 0;
}
int mov;
int fir = mdf[0], las = mdf[num - 1];
if (fir >= pos) mov = las - pos;
else if (las <= pos) mov = pos - fir;
else {
int l1 = fabs(pos - fir), l2 = fabs(pos - las);
if(l1 > l2) swap(l1, l2);
mov = 2 * l1 + l2;
}
cout << res + mov << endl;
return 0;
}
给出一棵树,节点有权值,问有多少 个集合S,使得集合中的元素满足 :1.S非空。 2.S中的点构成一条路径。3.S中点的最大权值和最小权值差小于等于d
树形DP
先考虑一种特殊情况,如果d是无穷大,那么权值就没有用了,我们可以假设树根是节点1,做一遍DFS,记Fi表示以i为根节点的子树中集合S的个数,j是节点i的子节点,则,复杂度是O(N)
再对于一般的情况,我们需把计算包含节点i的集合S个数,并且对于集合中的其他元素j有ai ≤ aj ≤ ai + d ,此时便变成了上述的情况, 因此我们可以枚举所有的点,按上述方法计算后累加即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
using namespace std;
const int N = 2010;
const int mod = 1000000007;
typedef long long ll;
int d, n;
int val[N];
vector<int> G[N];
ll dp[N];
void dfs(int u, int fa, int rt){
dp[u] = 1;
for(int i = 0; i < G[u].size(); ++i){
int v = G[u][i];
if(v == fa) continue;
if(val[v] >= val[rt] && val[v] <= val[rt] + d){
if(val[v] == val[rt] && v > rt) continue;
dfs(v, u, rt);
dp[u] = dp[u] * (dp[v] + 1) % mod;
}
}
}
int main(){
while(cin >> d >> n){
for(int i = 1; i <= n; ++i) cin >> val[i];
for(int i = 1; i <= n; ++i) G[i].clear();
int u, v;
for(int i = 1; i <= n - 1; ++i){
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
ll ans = 0;
for(int i = 1; i <= n; ++i){
memset(dp, 0, sizeof(dp));
dfs(i, -1, i);
ans = (ans + dp[i]) % mod;
}
cout << ans << endl;
}
return 0;
}
关于NlogN复杂度求LIS的算法可以参考点击打开链接
开始没有任何思路,看了题解,首先求出两个序列F1,F2,和LIS的长度l
-
Let F1i be the length of LIS ending exactly at ai of sequence {a1, a2, ..., ai}.
-
Let F2i be the length of LIS beginning exactly at ai of sequence {ai, ai + 1, ..., an}.
-
l = length of LIS of {a1, a2, ..., an} = max{F1i} = max{F2j}.
if F1i + F2i - 1 ≠ l than answer for i is 1, otherwise it is 2 or 3.
Then, assume there are two elements i and j with answer different from 1 such that F1i = F1j. You can prove that in this case you can replace i-th element with j-th one in any LIS containing i-th element. Thus the answer for i is 2 (and for j it is 2 too, of course). It can also be shown that if F1i is unique among all F1 then the answer for i is 3.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#define mem(x) memset(x, 0, sizeof(x))
using namespace std;
const int N = 100010;
typedef __int64 ll;
int a[N], b[N], f1[N], f2[N];
int dp[N];
int ans[N];
int n;
struct Data{
int id, val;
}d[N];
int fun(int x, int w){
int l = 1, r = w, mid;
while(l < r){
mid = l + (r - l) / 2;
if(dp[mid] <= b[x]) r = mid;
else l = mid + 1;
}
return r;
}
bool cmp(Data x, Data y){
if(x.val == y.val) return x.id < y.id;
else return x.val < y.val;
}
int main(){
while (cin >> n){
for (int i = 1; i <= n; ++i) cin >> a[i], b[n - i + 1] = a[i];
int len = 1;
dp[1] = a[1];
f1[1] = 1;
for(int i = 2; i <= n; ++i){
if(a[i] > dp[len]){
dp[++len] = a[i];
f1[i] = len;
}
else{
int pos = lower_bound(dp, dp + len, a[i]) - dp;
dp[pos] = a[i];
f1[i] = pos;
}
}
// cout << "len1 = " <<len << endl;
// for(int i = 1; i <= n; ++i) cout << f1[i] << " "; cout << endl;
dp[1] = b[1];
f2[n] = 1;
len = 1;
for(int i = 2; i <= n; ++i){
if(b[i] < dp[len]){
dp[++len] = b[i];
f2[n - i + 1] = len;
}
else{
int pos = fun(i, len);
dp[pos] = b[i];
//cout << "len = " << len << endl;
f2[n - i + 1] = pos;
}
}
// cout << "len2 = " << len << endl;
// for(int i = 1; i <= n; ++i) cout << f2[i] << " "; cout << endl;
int t = 0;
for(int i = 1; i <= n; ++i){
if(f1[i] + f2[i] - 1 != len) ans[i] = 1;
else{
d[t].id = i;
d[t++].val = f1[i];
}
}
sort(d, d + t, cmp);
if(t > 1) ans[d[0].id] = d[0].val == d[1].val ? 2 : 3;
else if(t == 1) ans[d[0].id] = 3;
for(int i = 1; i < t; ++i){
if(d[i].val == d[i - 1].val) ans[d[i].id] = ans[d[i - 1].id] = 2;
else ans[d[i].id] = 3;
}
for(int i = 1; i <= n; ++i) cout << ans[i];
cout << endl;
}
return 0;
}