求 ∑ i n ⌊ n i ⌋ \sum_{i}^{n} \left \lfloor \frac{n}{i} \right \rfloor ∑in⌊in⌋的奇偶性
分块求和的经典题目,kuangbin数论专题十四G - Harmonic Number (II)
题意略,
模拟题,转换成分钟,各种处理时间的技巧
给定一个序列 k 1 , k 2 , k 3 . . . k n {k_1,k_2,k_3...k_n} k1,k2,k3...kn 其中 k i k_i ki代表的值是 2 k i 2^{k_i} 2ki,要求把这k个数分成两堆,使得每一堆的值都大于1/2
利用二进制的原理,优先队列+并查集,先取出权值最小的,进行合并,如果两个值相同,则可以合并成一个k-1,最后判断是否有两个或两个以上的1出现即可
#include
#define mem(ar,num) memset(ar,num,sizeof(ar))
#define me(ar) memset(ar,0,sizeof(ar))
#define lowbit(x) (x&(-x))
#define Pb push_back
#define FI first
#define SE second
#define rep(i,a,n) for (int i=a;i
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define IOS ios::sync_with_stdio(false)
#define DEBUG cout<
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int prime = 999983;
const int INF = 0x7FFFFFFF;
const LL INFF =0x7FFFFFFFFFFFFFFF;
const double pi = acos(-1.0);
const double inf = 1e18;
const double eps = 1e-6;
const LL mod = 1e9 + 7;
LL qpow(LL a,LL b){LL s=1;while(b>0){if(b&1)s=s*a%mod;a=a*a%mod;b>>=1;}return s;}
LL gcd(LL a,LL b) {return b?gcd(b,a%b):a;}
int dr[2][4] = {1,-1,0,0,0,0,-1,1};
typedef pair<int,int> P;
const int maxn = 1e5+10;
int a[maxn];
int F[maxn];
int Find(int x){
return x == F[x]?x:F[x] = Find(F[x]);
}
int main(void)
{
int T;cin>>T;
int kase =0;
while(T--){
int n;cin>>n;
for(int i = 1;i <= n; ++i)
F[i] = i;
for(int i = 1;i <= n; ++i)
scanf("%d",&a[i]);
priority_queue<P>Q;
for(int i = 1;i <= n; ++i)
Q.push(P(a[i],i));
while(!Q.empty()&&Q.top().first > 1){
P p = Q.top(); Q.pop();
if(p.first != Q.top().first){
continue;
}
if(Q.empty()) break;
P p2 = Q.top();Q.pop();
int x = Find(p.second);
int y = Find(p2.second);
if(x < y)
swap(x,y);
F[x] = y;
Q.push(P(p.first-1,y));
}
printf("Case %d: ",++kase);
if(Q.size() < 2)
puts("NO");
else{
puts("YES");
for(int i = 1;i <= n; ++i){
int x = Find(i);
printf("%c",x == Q.top().second?'1':'0');
}
puts("");
}
}
return 0;
}
/*
3
6
2 100 2 2 100 2
*/
D和F的顺序记不清了,记错改一下
先说游戏:
给出三维空间起始点 x 0 , y 0 , z 0 ( z 0 > 0 ) x_0,y_0,z_0 \ (z_0 > 0) x0,y0,z0 (z0>0),给出方向矢量 v x , v y , v z v_x,v_y,v_z vx,vy,vz,求与圆锥相交的时间,圆锥底面圆的圆心在x,y平面的坐标原点,半径r,高 h,
射线方程
x = x 0 + v x x = x_0+v_x x=x0+vx
y = y 0 + v y y = y_0+v_y y=y0+vy
z = z 0 + v z z = z_0+v_z z=z0+vz
圆锥侧面方程
x 2 + y 2 r = h − z h \frac{\sqrt{x^{2} + y^{2} }}{r}=\frac{h-z}{h} rx2+y2=hh−z
计算几何,联立求解圆锥方程和直线方程,求出t,注意特殊情况就ok了
注意判断增根, 0 < = z < = h , x 2 + y 2 < = r 2 0 <= z <= h, x^2+y^2 <= r^2 0<=z<=h,x2+y2<=r2
傻逼题 a n s = ∑ i = 1 n ( r i − 2 ) ans = \sum_{i=1}^{n}(r_i-2) ans=∑i=1n(ri−2)
题意:
修改:将l,r 的所有字符串执行修改,在前后都加一个字符
查询:查询l,r 的和
分析:
我们发现这个修改操作满足可加行,两次修改可以合并成一个,类似区间加,用线段树维护以下value:
s u m [ o ] sum[o] sum[o] 代表区间 [ l , r ] [l,r] [l,r]的和
k 10 k10 k10 代表 k 10 = ∑ i ∈ [ l , r ] 2 l e n i k10 = \sum_{i \in [l,r]}{2^{len_i}} k10=∑i∈[l,r]2leni
修改可以看做分解
a d d l e f t = 左 边 加 的 部 分 addleft = 左边加的部分 addleft=左边加的部分
a d d r i g h t = 右 边 加 的 部 分 addright = 右边加的部分 addright=右边加的部分
a d d l e n = 加 入 字 符 串 的 个 数 addlen = 加入字符串的个数 addlen=加入字符串的个数
然后按照相应规则进行更新
例如:只加入一个字符
tree[o].addleft = (v * pow10[tree[o].addlen] + tree[o].addleft) % mod;
tree[o].addright = (tree[o].addright * 10 + v) % mod;
tree[o].addlen += 1;
tree[o].sum = ( tree[o].sum * 10 + tree[o].k10 * v%mod * 10 + v * (r - l + 1)) % mod;
// cout << tree[o].sum << endl;
tree[o].k10 = (tree[o].k10 * 100) % mod;
参考代码
#include
#define mem(ar,num) memset(ar,num,sizeof(ar))
#define me(ar) memset(ar,0,sizeof(ar))
#define lowbit(x) (x&(-x))
#define Pb push_back
#define FI first
#define SE second
#define rep(i,a,n) for (int i=a;i
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define IOS ios::sync_with_stdio(false)
#define DEBUG cout<
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int prime = 999983;
// const int INF = 0x7FFFFFFF;
const LL INFF = 0x7FFFFFFFFFFFFFFF;
const double pi = acos(-1.0);
const double inf = 1e18;
const double eps = 1e-6;
const LL mod = 1e9 + 7;
LL qpow(LL a, LL b) {LL s = 1; while (b > 0) {if (b & 1)s = s * a % mod; a = a * a % mod; b >>= 1;} return s;}
LL gcd(LL a, LL b) {return b ? gcd(b, a % b) : a;}
int dr[2][4] = {1, -1, 0, 0, 0, 0, -1, 1};
typedef pair<int, int> P;
#define lson (o << 1)
#define rson (o << 1|1)
const int maxn = 1e5 + 10;
const int INF = 1e9;
typedef long long LL;
LL pow10[maxn * 3];
struct Tree {
LL sum, k10, addleft, addright, addlen;
int l, r;
};
Tree tree[maxn << 2];
void pushup(int o, int l, int r) {
tree[o].sum = (tree[lson].sum + tree[rson].sum) % mod;
tree[o].k10 = (tree[lson].k10 + tree[rson].k10) % mod;
}
void Add(Tree &b, Tree &a) {
b.sum = ( b.sum * pow10[ a.addlen] + a.addleft * b.k10%mod * pow10[a.addlen] + a.addright * (b.r - b.l + 1)) % mod;
b.k10 = (b.k10 * pow10[2 * a.addlen]) % mod;
b.addleft = (b.addleft + a.addleft * pow10[b.addlen]) % mod;
b.addright = (b.addright * pow10[a.addlen] + a.addright) % mod;
b.addlen = b.addlen + a.addlen;
}
void pushdown(int o, int l, int r) {
if (tree[o].addlen > 0) {
Add(tree[lson], tree[o]);
Add(tree[rson], tree[o]);
tree[o].addlen = tree[o].addright = tree[o].addleft = 0;
}
}
void up(Tree & a, Tree b) {
a.sum = (a.sum + b.sum) % mod;
}
void build(int o, int l, int r) {
tree[o].l = l;
tree[o].r = r;
// cout<
// tree[o].add = 0;
tree[o].k10 = (r - l + 1);
if (l == r)
{
tree[o].sum = tree[o].addright = tree[o].addleft = tree[o].addlen = 0;
// cout<
}
else {
int m = (l + r) >> 1;
build(lson, l, m);
build(rson, m + 1, r);
}
}
void Update(int o, int l, int r, int L, int R, int v) {
// cout << tree[o].k10 << endl;
if (L <= l && R >= r) {
tree[o].addleft = (v * pow10[tree[o].addlen] + tree[o].addleft) % mod;
tree[o].addright = (tree[o].addright * 10 + v) % mod;
tree[o].addlen += 1;
tree[o].sum = ( tree[o].sum * 10 + tree[o].k10 * v%mod * 10 + v * (r - l + 1)) % mod;
// cout << tree[o].sum << endl;
tree[o].k10 = (tree[o].k10 * 100) % mod;
return ;
}
pushdown(o, l, r);
int m = (l + r) / 2;
if (L <= m)
Update(lson, l, m, L, R, v);
if (R > m)
Update(rson, m + 1, r, L, R, v);
pushup(o, l, r);
}
Tree Query(int o, int l, int r, int L, int R) {
if (L <= l && R >= r)
{
return tree[o];
}
Tree tmp;
tmp.sum = 0;
pushdown(o, l, r);
int m = (l + r) >> 1;
if (L <= m)
up(tmp, Query(lson, l, m, L, R));
if (R > m)
up(tmp, Query(rson, m + 1, r, L, R));
// cout<
return tmp;
}
int n, m;
// char
int main(void) {
pow10[0] = 1;
for (int i = 1; i < maxn * 3; ++i)
pow10[i] = pow10[i - 1] * 10 % mod;
// cout << pow10[2] << endl;
int T; cin >> T;
int kase = 0;
while (T--) {
printf("Case %d:\n", ++kase);
cin >> n >> m;
me(tree);
build(1, 1, n);
while (m--) {
char op[10];
int l, r, d;
scanf("%s%d%d", op, &l, &r);
if (op[0] == 'w') {
scanf("%d", &d);
Update(1, 1, n, l, r, d);
}
else {
printf("%lld\n", Query(1, 1, n, l, r).sum);
}
}
}
return 0;
}
/*
2
3 4
wrap 1 1 1
wrap 1 2 1
wrap 1 3 1
query 1 3
2
4 4
wrap 1 3 0
wrap 2 4 3
query 1 4
query 2 3
*/