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;
}