这次没有爆零
有点感动
题解链接:https://pan.baidu.com/s/1b9i0yI1oEDcaCZc_SH-K3Q 提取码: k2xc 复制这段内容后打开百度网盘手机App,操作更方便哦
题目大意:有一个数x 在范围0~ (2^n)-1 内
询问 一个数 y 给出答案 x & y==y
可以询问多次 询问之后 一起给出回答
可以简单证明得到
范围是 0~(2^n)-1时 需要n个数得到最小的方案数
因为两个方案的询问次序不同可算作两种方案
所以 答案是 n !
PS:当n>1000003 时 乘积已经可以整除1000003了 得到0
举个栗子:
#include
#include
#include
#include
#include
using namespace std;
#define ll long long
int const mod = 1e6 + 3;
ll a[1000005];
int main()
{
int n;
ll ans = 1;
for (int i = 1; i < 1000005; i++) {
ans = (ans * i) % mod;
a[i] = ans;
}
while (~scanf("%d", &n)) {
if (n >= mod) {
printf("0\n");
} else {
printf("%lld\n", a[n]);
}
}
return 0;
}
所以分子是 3 8 15 24……
分母是9
(不是我推的 我好菜啊TAT)
然后求逆元emmm
#include
#include
#include
#include
#include
using namespace std;
#define ll long long
ll const mod = 998244353;
ll quickpow(ll x, ll n)
{
int res = x;
int ans = 1;
while (n) {
if (n & 1) {
ans = (ans % mod * (res % mod)) % mod ;
}
res = (res % mod * (res % mod)) % mod ;
n = n >> 1;
}
return ans;
}
int main()
{
int n;
while (~scanf("%d", &n)) {
ll t = 3;
ll ans = 0;
for (int i = 1; i < n; i++) {
ans += t;
t = t + 2;
}
// printf("%lld\n", quickpow(9,mod-2)%mod);
printf("%lld\n", (ans * quickpow(9, mod - 2)) % mod);
}
return 0;
}
参考:https://www.cnblogs.com/Chen-Jr/p/11240189.html
用了bin巨的模板 但是 这是找主席树第K小的
所以在最后算三角形周长的时候需要 变换一下
找最大的能组成三角形的三个数
#include
#include
#include
#include
#include
#include
using namespace std;
#define ll long long
const int maxn = 100010;
const int M = maxn * 30;
int q, n, m, tot;
int a[maxn], t[maxn];
int T[maxn], lson[M], rson[M], c[M];
void Init_hash()//将数组复制到另一个数组 并排序去重
{
for (int i = 1; i <= n; i++) {
t[i] = a[i];
}
sort(t + 1, t + 1 + n);
m = unique(t + 1, t + 1 + n) - t - 1;
}
int build(int l, int r)//建树
{
int root = tot++;
c[root] = 0;
if (l != r) {
int mid = (l + r) >> 1;
lson[root] = build(l, mid);
rson[root] = build(mid + 1, r);
}
return root;
}
int Hash(int x)//快速找到x的位置
{
return lower_bound(t + 1, t + 1 + m, x) - t;
}
int update(int root, int pos, int val)//更新节点
{
int newroot = tot++, tmp = newroot;
c[newroot] = c[root] + val;
int l = 1, r = m;
while (l < r) {
int mid = (l + r) >> 1;
if (pos <= mid) {
lson[newroot] = tot++;
rson[newroot] = rson[root];
newroot = lson[newroot];
root = lson[root];
r = mid;
} else {
rson[newroot] = tot++;
lson[newroot] = lson[root];
newroot = rson[newroot];
root = rson[root];
l = mid + 1;
}
c[newroot] = c[root] + val;
}
return tmp;
}
int query(int left_root, int right_root, int k)//查询l ~r中第k小的
{
int l = 1, r = m;
while (l < r) {
int mid = (l + r) >> 1;
if (c[lson[left_root]] - c[lson[right_root]] >= k) {
r = mid;
left_root = lson[left_root];
right_root = lson[right_root];
} else {
l = mid + 1;
k -= c[lson[left_root]] - c[lson[right_root]];
left_root = rson[left_root];
right_root = rson[right_root];
}
}
return l;
}
int main()
{
while (~scanf("%d%d", &n, &q)) {
tot = 0;
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
Init_hash();
T[n + 1] = build(1, m);
for (int i = n; i > 0; i--) {
int pos = Hash(a[i]);
T[i] = update(T[i + 1], pos, 1);
}
while (q--) {
int l, r, k;
scanf("%d%d", &l, &r);
int m = r - l + 1;
ll ans = -1;
while (m >= 3) {
int a = t[query(T[l], T[r + 1], m)];
int b = t[query(T[l], T[r + 1], m - 1)];
int c = t[query(T[l], T[r + 1], m - 2)];
if (b + c > a) {
ans = 1ll * a + 1ll * b + 1ll * c ;
break;
}
m--;
}
printf("%lld\n", ans);
}
}
return 0;
}
题目大意:给 n 个数字,这串数字中范围是1~c,合法条件是某一段区间内出现任何一个数字,它出现的次数>=k或者=0
求合法条件下的最长连续子序列的长度是多少?