A
:
S
u
b
o
r
r
a
y
s
A: Suborrays
A:Suborrays
思路:
x
∣
y
>
=
m
a
x
(
x
,
y
)
x|y>=max(x,y)
x∣y>=max(x,y),线性输出即可。
参考代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <math.h>
using namespace std;
typedef long long ll;
//#define ll long long
const int N = 2009;
const ll maxn = 1e5 + 20;
const ll mod = 1000000007;
int inv[maxn], vis[maxn], dis[maxn];
int fac[maxn], a[maxn], q[maxn], b[N], c[N];
vector<ll> vec;
//typedef pair<ll, ll> p;
//priority_queue<p, vector<p>, greater<p> > m;
// ll sum[maxn], a[maxn];
ll max(ll a, ll b) { return a > b ? a : b; }
ll min(ll a, ll b) { return a < b ? a : b; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b); }
map<ll, ll> mp;
ll ksm(ll a, ll b)
{
a %= mod;
ll ans = 1ll;
while (b)
{
if (b & 1)
ans = (ans * a) % mod;
a = (a * a) % mod;
b >>= 1ll;
}
return ans;
}
int dp[N][N];
char s[N][N];
// string p = "abacaba";
// queue<ll> qk, q;
//vector<ll> vec;
// ll sumx[maxn], sumy[maxn], sumk[maxn];
int cnt;
map<int, int> p;
struct node
{
int ls, rs, sum;
} tr[maxn * 32];
void inser(int &k, int L, int R, int pos, int w)
{
if (!k)
k = ++cnt;
tr[k].sum += w;
if (L == R)
return;
int mid = L + R >> 1;
if (mid >= pos)
inser(tr[k].ls, L, mid, pos, w);
else
inser(tr[k].rs, mid + 1, R, pos, w);
}
int query(int k, int L, int R, int ik)
{
if (L == R)
return L;
int sk = tr[tr[k].ls].sum;
int mid = L + R >> 1;
if (sk >= ik)
return query(tr[k].ls, L, mid, ik);
else
return query(tr[k].rs, mid + 1, R, ik - sk);
}
int lx[N][N], rx[N][N], bl[N][N], br[N][N], wup[N][N], down[N][N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
//ll t, n, ans;
// scanf("%lld", &t);
int t, n;
cin >> t;
while (t--)
{
cin >> n;
for (int i = 1; i <= n; i++)
cout << i << ' ';
cout << endl;
}
}
B − F i x Y o u B - Fix You B−FixYou
思路:
由于只能往下走或往右走,所以我们只考虑,最下一行的能否到达,和最右一列的能否到达即可,因为其他的点必然会经过最后一行或者最右一列。
参考代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <math.h>
using namespace std;
typedef long long ll;
//#define ll long long
const int N = 2009;
const ll maxn = 1e5 + 20;
const ll mod = 1000000007;
int inv[maxn], vis[maxn], dis[maxn];
int fac[maxn], a[maxn], q[maxn], b[N], c[N];
vector<ll> vec;
//typedef pair<ll, ll> p;
//priority_queue<p, vector<p>, greater<p> > m;
// ll sum[maxn], a[maxn];
ll max(ll a, ll b) { return a > b ? a : b; }
ll min(ll a, ll b) { return a < b ? a : b; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b); }
map<ll, ll> mp;
ll ksm(ll a, ll b)
{
a %= mod;
ll ans = 1ll;
while (b)
{
if (b & 1)
ans = (ans * a) % mod;
a = (a * a) % mod;
b >>= 1ll;
}
return ans;
}
int dp[N][N];
char s[N][N];
// string p = "abacaba";
// queue<ll> qk, q;
//vector<ll> vec;
// ll sumx[maxn], sumy[maxn], sumk[maxn];
int cnt;
map<int, int> p;
struct node
{
int ls, rs, sum;
} tr[maxn * 32];
void inser(int &k, int L, int R, int pos, int w)
{
if (!k)
k = ++cnt;
tr[k].sum += w;
if (L == R)
return;
int mid = L + R >> 1;
if (mid >= pos)
inser(tr[k].ls, L, mid, pos, w);
else
inser(tr[k].rs, mid + 1, R, pos, w);
}
int query(int k, int L, int R, int ik)
{
if (L == R)
return L;
int sk = tr[tr[k].ls].sum;
int mid = L + R >> 1;
if (sk >= ik)
return query(tr[k].ls, L, mid, ik);
else
return query(tr[k].rs, mid + 1, R, ik - sk);
}
int lx[N][N], rx[N][N], bl[N][N], br[N][N], wup[N][N], down[N][N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
//ll t, n, ans;
// scanf("%lld", &t);
int t, n, m;
cin >> t;
while (t--)
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> (s[i] + 1);
int ans = 0;
for (int i = 1; i < m; i++)
{
if (s[n][i] != 'R')
ans++;
}
for (int i = 1; i < n; i++)
{
if (s[i][m] != 'D')
ans++;
}
cout << ans << endl;
}
}
C
:
C
y
c
l
i
c
P
e
r
m
u
t
a
t
i
o
n
s
C:Cyclic Permutations
C:CyclicPermutations
思路:
没啥思路这个,我题其实没怎么看懂,但是几分钟就A了,因为能看出这个是个规律题,那么对于规律题,一般都是阶乘,
2
n
2^n
2n,
n
k
n^k
nk之类的,我随意构造了几个,发现第一个过了,第二个也过了,就A了 。
参考代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <math.h>
using namespace std;
typedef long long ll;
//#define ll long long
const int N = 2009;
const ll maxn = 1e5 + 20;
const ll mod = 1000000007;
int inv[maxn], vis[maxn], dis[maxn];
int fac[maxn], a[maxn], q[maxn], b[N], c[N];
vector<ll> vec;
//typedef pair<ll, ll> p;
//priority_queue<p, vector<p>, greater<p> > m;
// ll sum[maxn], a[maxn];
ll max(ll a, ll b) { return a > b ? a : b; }
ll min(ll a, ll b) { return a < b ? a : b; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b); }
map<ll, ll> mp;
ll ksm(ll a, ll b)
{
a %= mod;
ll ans = 1ll;
while (b)
{
if (b & 1)
ans = (ans * a) % mod;
a = (a * a) % mod;
b >>= 1ll;
}
return ans;
}
ll dp[1000005];
char s[N][N];
// string p = "abacaba";
// queue<ll> qk, q;
//vector<ll> vec;
// ll sumx[maxn], sumy[maxn], sumk[maxn];
int cnt;
map<int, int> p;
struct node
{
int ls, rs, sum;
} tr[maxn * 32];
void inser(int &k, int L, int R, int pos, int w)
{
if (!k)
k = ++cnt;
tr[k].sum += w;
if (L == R)
return;
int mid = L + R >> 1;
if (mid >= pos)
inser(tr[k].ls, L, mid, pos, w);
else
inser(tr[k].rs, mid + 1, R, pos, w);
}
ll f()
{
dp[0] = 1;
for (ll i = 1; i <= 1000005; i++)
dp[i] = dp[i - 1] * i % mod;
}
int query(int k, int L, int R, int ik)
{
if (L == R)
return L;
int sk = tr[tr[k].ls].sum;
int mid = L + R >> 1;
if (sk >= ik)
return query(tr[k].ls, L, mid, ik);
else
return query(tr[k].rs, mid + 1, R, ik - sk);
}
int lx[N][N], rx[N][N], bl[N][N], br[N][N], wup[N][N], down[N][N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
//cout << (583291ll * 583291ll % mod) << endl;
//ll t, n, ans;
// scanf("%lld", &t);
ll t, n, m;
// cin >> t;
f();
// while (t--)
// {
cin >> n;
cout << ((dp[n] - ksm(2, n - 1) + mod) % mod) << endl;
// }
}
D − 505 D - 505 D−505
思路:枚举子集+贪心
可以确定的是当
n
>
3
n>3
n>3时无解,因为由于
m
>
=
n
m>=n
m>=n,所以当
n
>
3
n>3
n>3,
n
,
m
n,m
n,m组成的大矩阵中一定含
4
∗
4
4*4
4∗4的小矩阵,证明
4
∗
4
4*4
4∗4的矩阵无解如下图:
所以现在我们可以确定
n
n
n的范围属于
[
1
,
3
]
[1,3]
[1,3],显然这么小的数据范围是可以枚举的,所以我们枚举第一列的状态,的到该状态的01序列,通过第一列的状态构造符合条件的矩阵,在构造中获得每一种状态修改的次数,枚举最小值。
若
n
=
1
n=1
n=1,答案直接输出
0
0
0即可,
n
>
3
n>3
n>3输出
−
1
-1
−1,
n
=
2
∣
∣
n
=
3
n=2||n=3
n=2∣∣n=3,构造合法答案,显然我们已知第一列的状态,第二列的状态可由给定矩阵构造出,直至构造到第
m
m
m列,具体操作看一下代码。
参考代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <math.h>
using namespace std;
typedef long long ll;
//#define ll long long
const int N = 2009;
const ll maxn = 1e5 + 20;
const ll mod = 1000000007;
int inv[maxn], vis[maxn], dis[maxn];
int fac[maxn], a[maxn], q[maxn], b[N], c[N];
vector<ll> vec;
//typedef pair<ll, ll> p;
//priority_queue<p, vector<p>, greater<p> > m;
// ll sum[maxn], a[maxn];
ll max(ll a, ll b) { return a > b ? a : b; }
ll min(ll a, ll b) { return a < b ? a : b; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a * b / gcd(a, b); }
map<ll, ll> mp;
ll ksm(ll a, ll b)
{
a %= mod;
ll ans = 1ll;
while (b)
{
if (b & 1)
ans = (ans * a) % mod;
a = (a * a) % mod;
b >>= 1ll;
}
return ans;
}
// ll dp[1000005];
// char s[N][N];
// // string p = "abacaba";
// // queue<ll> qk, q;
// //vector<ll> vec;
// // ll sumx[maxn], sumy[maxn], sumk[maxn];
// int cnt;
// map<int, int> p;
int dp[3][1000005];
string matrix[1000005];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t, n, m;
// cin >> t;
//f();
// while (t--)
// {
cin >> n >> m;
for (int i = 0; i < n; i++)
cin >> matrix[i];
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
matrix[i][j] -= '0';
if (n == 1)
cout << 0 << endl;
else if (n >= 4)
cout << -1 << endl;
else
{
int ans = 999999999;
for (int i = 0; i < (1 << n); i++)
{
int cur = 0;
for (int j = 0; j < n; j++)
{
dp[j][0] = (i >> j) & 1;
if (matrix[j][0] != dp[j][0])
cur++;
}
for (int j = 1; j < m; j++)
{
dp[0][j] = matrix[0][j];
dp[1][j] = matrix[1][j];
dp[2][j] = matrix[2][j];
int res1 = dp[0][j] + dp[1][j] + dp[0][j - 1] + dp[1][j - 1];
if (n == 3)
{
int res2 = dp[1][j] + dp[2][j] + dp[1][j - 1] + dp[2][j - 1];
if ((res1 & 1) && (res2 & 1))
continue;
if (res1 & 1)
dp[2][j] ^= 1, cur++;
else if (res2 & 1)
dp[0][j] ^= 1, cur++;
else
dp[1][j] ^= 1, cur++;
}
else
{
if (!(res1 & 1))
dp[0][j] ^= 1, cur++;
}
}
ans = min(cur, ans);
}
cout << ans << endl;
}
// }
}