[考试总结]noip模拟52
似乎这个是一个暴力能够 \(ak\) 的比赛。。。
然后正道的光,然后把所有暴力卡没。。。
异或
这个题目还是比较水的吧。。。
考场上想了有一段时间,然后发现了这个规律:
\[f_i = f_{i-1} << 1 + 1
\]
这个下标代表的是 \(2^i\) 的前缀和。
然后就可以开始倍增。
然后就能愉快 \(AC\)
然后我们还发现这个玩意儿实质上就是这个。。。
for(register signed i=1;i<=n;i<<=1) ans += n / i;
然后不到 \(20byte\) 解决。。。
#include<bits/stdc++.h>
#define int long long
signed main()
{
int n,ans = 0;std::cin>>n;
for(register int i=1;i<=n;i<<=1)
ans += n / i;
std::cout<<ans<<std::endl;
}
赌神
考场上面盲猜了一个结论。。。
就是对面想要抹平这个序列,然后我自己的策略就是把这个玩意按比例分配,并且每次把所有钱都放完。
然后其实优先队列很快,然而被我删掉了。。。。
然后就有 \(80pts\)
但是实际上并不用排序。。。
然后很快。
\(\mathcal O(n)\)
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
#define file(a,b) freopen(#a"","r",stdin),freopen(#b"","w",stdout)
#define sb(x) cout<<#x" = "<<x<<' '
#define jb(x) cout<<#x" = "<<x<<endl
#define debug cout<<"debug"<<endl
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &s)
{
register int f = 0;s = 0; register char ch = gc();
while(!isdigit(ch)) {f |= ch == '-'; ch = gc();}
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
}}io;
}
using namespace xin_io;static const int maxn = 1e6+10,inf = 1e9+7;const ll llinf = 1e18+7;
#define int long long
namespace xin
{
const int mod = 998244353;
int n,ans = 0;
int temp[maxn],inv[maxn],a[maxn];
std::priority_queue<int>q;
auto ksm = [](int x,int y,int ret = 1) -> int
{
while(y)
{
if(y & 1) ret = ret * x % mod;
x = x * x % mod; y >>= 1;
}
return ret;
};
int sum = 0;
inline short main()
{
io >> n;
try(i,1,n) io >> a[i],q.push(a[i]),sum += a[i];
if(n == 1)
{
cout<<1<<endl;
return 0;
}
inv[0] = inv[1] = 1;
try(i,2,sum) inv[i] = (mod - mod / i) * inv[mod % i] % mod;
ans = 1;
while(sum)
{
// try(i,1,n) cout<<a[i]<<' '; cout<<endl;
register int x = q.top(); q.pop();
temp[1] = ans * x % mod * inv[sum] % mod;//,cout<<temp[i]<<' ';cout<<endl;
ans = temp[1] * n % mod;
q.push(x-1); sum --;
}
cout<<ans<<endl;
return 0;
}
}
signed main() {return xin::main();}
路径
点分治球出来每一种 \(dis\) 的数量。
然后暴力统计。
然后可以被卡到 \(30pts\)
但是数据过于垃圾!
然后可以过掉。。。。
正解我们来一个换跟 \(dp\)
然后式子中的 \(x^k\) 用斯特林展开
然后就能过了。。
常数还是挺大的。
\(nb\) 评测机跑了整整三秒。。。
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define int long long
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
#define file(a,b) freopen(#a"","r",stdin),freopen(#b"","w",stdout)
#define sb(x) cout<<#x" = "<<x<<' '
#define jb(x) cout<<#x" = "<<x<<endl
#define debug cout<<"debug"<<endl
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &s)
{
register int f = 0;s = 0; register char ch = gc();
while(!isdigit(ch)) {f |= ch == '-'; ch = gc();}
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
}}io;
}
using namespace xin_io;static const int maxn = 1e6+10,inf = 1e9+7;const ll llinf = 1e18+7;
namespace xin
{
const int mod = 998244353;
// const int mod = 10007;
auto ksm = [](int x,int y,int ret = 1) -> int
{
while(y)
{
if(y & 1) ret = ret * x % mod;
x = x * x % mod; y >>= 1;
}
return ret;
};
signed f1[maxn][101],f2[maxn][101];
int C[maxn/1000][maxn/1000],temp[maxn],fac[maxn];
int n,k;
class xin_edge{public:int next,ver;}edge[maxn<<1];
int head[maxn],rp;
auto add = [](int x,int y) -> void {edge[++rp].ver = y;edge[rp].next = head[x]; head[x] = rp;};
void dfs1(int x,int f)
{
f1[x][0] = 1;
go(i,x)
{
if(y == f) continue;
dfs1(y,x);
try(j,1,k) (f1[x][j] += (f1[y][j] + f1[y][j-1]) % mod) %= mod;
(f1[x][0] += f1[y][0]) %= mod;
}
}
void dfs2(int x,int f)
{
try(i,0,k) f2[x][i] = f1[x][i];
if(f)
{
try(i,1,k) temp[i] = (ll)(f2[f][i] - f1[x][i] + mod - f1[x][i-1] + mod) % mod;
temp[0] = (ll)(f2[f][0] - f1[x][0] + mod) % mod;
try(i,1,k) (f2[x][i] += (temp[i] + temp[i-1]) % mod) %= mod;
(f2[x][0] += temp[0]) %= mod;
}
go(i,x)
{
if(y == f) continue;
dfs2(y,x);
}
}
inline short main()
{
io >> n >> k;
try(i,1,n-1)
{
register int x,y; io >> x >> y;
add(x,y); add(y,x);
}
fac[0] = 1; try(i,1,k) fac[i] = fac[i-1] * i % mod;
C[0][0] = C[1][1] = 1;
try(i,2,k) try(j,1,i)
C[i][j] = (C[i-1][j] * j + C[i-1][j-1]) % mod;
dfs1(1,0); dfs2(1,0);
int ans = 0;
try(i,1,n)
{
try(j,0,k) (ans += C[k][j] * fac[j] % mod * f2[i][j] % mod) %= mod;
// printf("%lld\n",ans);
}
cout<<ans * ksm(2,mod-2) % mod<<endl;
return 0;
}
}
signed main() {return xin::main();}
``
# 树
对于每一个深度建一个动态开点线段树。
然后暴力跳深度。
然后就行了。
## 当然这个不是正解!!!
然后正解是树上分块。
但是挺慢的。。。
```cpp
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
#define file(a,b) freopen(#a"","r",stdin),freopen(#b"","w",stdout)
#define sb(x) cout<<#x" = "<<x<<' '
#define jb(x) cout<<#x" = "<<x<<endl
#define debug cout<<"debug"<<endl
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &s)
{
register int f = 0;s = 0; register char ch = gc();
while(!isdigit(ch)) {f |= ch == '-'; ch = gc();}
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
}}io;
}
using namespace xin_io;static const int maxn = 2e6+10,inf = 1e9+7;const ll llinf = 1e18+7;
namespace xin
{
auto max = [](int x,int y) -> int{return x > y ? x : y;};
auto min = [](int x,int y) -> int{return x < y ? x : y;};
int n,m,maxdep;
class xin_edge{public:int next,ver;}edge[maxn];
int head[maxn],rp;
auto add = [](int x,int y) -> void {edge[++rp].ver = y; edge[rp].next = head[x]; head[x] = rp;};
int d[maxn],fa[maxn],rt[maxn],id[maxn],siz[maxn],tot;
void dfs(int x,int f)
{
d[x] = d[f] + 1; maxdep = max(d[x],maxdep);
id[x] = ++tot; siz[x] = 1;
go(i,x)
{
if(y == f) continue;
dfs(y,x); siz[x] += siz[y];
}
}
class xin_seg
{
private:
#define ls(fa) (t[fa].lson)
#define rs(fa) (t[fa].rson)
std::function<void(int)> up = [&](int fa) -> void{t[fa].s = t[ls(fa)].s + t[rs(fa)].s;};
std::function<void(int,int,int)> down = [&](int fa,int l,int r) -> void
{
if(!t[fa].debt) return ;
register int mid = l + r >> 1;
t[ls(fa)].s += (mid - l + 1) * t[fa].debt; t[rs(fa)].s += (r - mid) * t[fa].debt;
t[ls(fa)].debt += t[fa].debt; t[rs(fa)].debt += t[fa].debt;
t[fa].debt = 0;
};
public:
class xin_tree{public:int s,lson,rson,debt;}t[maxn<<4]; int tot = 0;
void modify(int &fa,int l,int r)
{
if(!fa) fa = ++tot;
if(l == r) return ;
register int mid = l + r >> 1;
modify(ls(fa),l,mid); modify(rs(fa),mid+1,r);
}
void insert(int &fa,int l,int r,int ql,int qr,int val)
{
if(!fa) fa = ++tot;
if(ql <= l and qr >= r) return t[fa].s += val * (r - l + 1),t[fa].debt += val,void();
register int mid = l + r >> 1; down(fa,l,r);
if(ql <= mid) insert(ls(fa),l,mid,ql,qr,val); if(qr > mid) insert(rs(fa),mid+1,r,ql,qr,val);
up(fa);
}
int query(int fa,int l,int r,int pos)
{
if(l == r) return t[fa].s; register int mid = l + r >> 1; down(fa,l,r);
if(pos <= mid) return query(ls(fa),l,mid,pos); else return query(rs(fa),mid+1,r,pos);
}
}t;
inline short main()
{
io >> n >> m;
try(i,1,n-1)
{
register int x,y; io >> x >> y;
add(x,y); add(y,x);
}
dfs(1,0);
try(i,1,maxdep) t.modify(rt[i],1,n);
try(que,1,m)
{
register int op; io >> op;
if(op == 1)
{
register int x,mod,dis,val; io >> x >> mod >> dis >> val;
for(register int i=d[x]+dis;i<=maxdep;i+=mod) t.insert(rt[i],1,n,id[x],id[x]+siz[x]-1,val);
}
else {register int x;io >> x; printf("%d\n",t.query(rt[d[x]],1,n,id[x]));}
}
return 0;
}
}
signed main() {return xin::main();}