昨晚打cf太晚了,今天早上又去做了核酸,写完8.30号的时候,已经11点多了。然后,早上没学习,下午又玩到了3点,才开始学习。学了一会,去地里看了看杂草,然后写题写到八点多,就在打王者。然后又做饭,啧,今天感觉根本就没怎么学习。
错排:a[i]==i的情况有Cnm,我们只需要考虑不同的情况。不同的话,显然,d[1]=0;d[2]=1;对于1,2来说,如果1选2,2选1,则情况有d[i-2]种,如果1选2,2不能选1的话,这样就和1不能选1,相同了。因此,剩下的d[i]=(i-1) *(d[i-1]+d[i-2])种, 则最终结果为 Cnm*(d[n-m])
注意:当n==m 结果为1,当 n-m==1,结果为0,当m==0,结果为d[n],其余的可以根据上述表达式解决。明天需要总结组合数,那几个算法。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define inf 1e9
#define x first
#define y second
typedef long long ll;
typedef pair<int, int>pii;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
int qumi(int a, int k, int p)
{
int res = 1;
while (k)
{
if (k & 1) res = res * a % p;
a = a * a % p;
k >>= 1;
}
return res;
}
int d[N];
int f[N];
int inv[N];
void init()
{
d[1] = 0; d[2] = 1;
for (int i = 3; i <= N; i++)
d[i] = (i - 1) * (d[i - 1] + d[i - 2]) % mod;
f[0] = 1; inv[0] = 1;
for(int i=1;i<=N;i++)
{
f[i] = f[i-1] * i % mod;
inv[i] = inv[i-1] * qumi(i, mod -2, mod) % mod;
}
}
signed main()
{
ios::sync_with_stdio(false); cin.tie(0); cin.tie(0);
init();
int t = 1;
cin >> t;
while (t--)
{
int n, m;
cin >> n >> m;
if(m == n) cout << 1 << endl;
else if(n - m == 1) cout << 0 << endl;
else if(m == 0) cout << d[n] << endl;
else
{
int res = f[n] * inv[n - m] % mod * inv[m] % mod;
cout << res * d[n - m] % mod << endl;
}
}
return 0;
}
题意:给你n个矩形,长宽分别为li,wi,q次询问,问有多少个矩形在第一个矩形和第二个矩形之中,求出面积。
解析:我们可以把矩形的宽度和长度,当x值,y值,这样就转换为一个二维前缀和的问题。因为必须严格大于,或者是严格小于,因此,需要++,或者是--。
vector,二维数组的创建方式,也需要学习一下。
void solve()
{
vector s(1010, vector<int>(1010));
int n, m; cin >> n >> m;
for (int i = 1; i <= n; i++)
{
int x, y;
cin >> x >> y;
s[x][y] += x * y;
}
for (int i = 1; i <= 1000; i++)
{
for (int j = 1; j <= 1000; j++)
{
s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
// cout << s[i][j] << endl;
}
// cout << i ;
}
// cout << 111 << endl;
while (m--)
{
int x1, y1, x2, y2;
cin >> x1 >> y1 >> x2 >> y2;
x1++, y1++;
x2--, y2--;
cout << s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1] << endl;
}
}
题意:询问有多少个L,’L‘可以进行反转,且互相之间不能相连。
解析:采用bfs,枚举八个方向,找连通块中*的个数,其必须为3。 但是还可能出现***,或者是纵向的,或者是斜着。因此,我们需要判断这三个*的相对位置。
int dis(pii a, pii b)
{
return abs(a.first - b.first) + abs(a.second - b.second);
}
bool bfs(int tx, int ty)
{
queue<pii> q;
q.push({tx, ty});
st[tx][ty] = true;
int dx[] = {-1, 1, 0, 0, -1, -1, 1, 1};
int dy[] = {0, 0, 1, -1, -1, 1, -1, 1};
int num = 1;
vector<pii> v;
while (!q.empty())
{
auto t = q.front();
q.pop();
for (int i = 0; i < 8; i++)
{
int x = t.first + dx[i];
int y = t.second + dy[i];
if (x < 1 || x > n || y < 1 || y > m)
continue;
if (st[x][y] || a[x][y] == '.')
continue;
num++;
q.push({x, y});
st[x][y] = true;
v.push_back({x, y});
}
}
// cout << num << endl;
bool ok = true;
if (v.size() != 2)
return false;
pii t = {tx, ty};
if ((dis(v[0], t) == 1 && dis(v[1], t) == 1))
ok = true;
else if ((dis(v[0], t) == 1 && dis(v[1], t) == 2 && dis(v[0], v[1]) == 1))
ok = true;
else if (dis(v[1], t) == 1 && dis(v[0], t) == 2 && dis(v[0], v[1]) == 1)
ok = true;
else
ok = false;
if (v[0].first == v[1].first && v[1].first == tx)
ok = false;
if (v[0].second == v[1].second && v[1].second == ty)
ok = false;
// cout << ok <<" "<< num << endl;
if (num != 3 || !ok)
return false;
else
return true;
}
void solve()
{
memset(st, false, sizeof st);
cin >> n >> m;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> a[i][j];
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (a[i][j] == '*' && !st[i][j])
{
if (bfs(i, j) == false)
{
cout << "NO" << endl;
return;
}
}
}
}
cout << "YES" << endl;
}