A. 奥义商店

有一个商店,n个物品,每个物品有一个价格和一种颜色。

有m个操作,操作有两种,一种是修改一个位置的价格,另一种是购买,每次购买指定一个公差d和一个位置k,找到包含这个位置k公差为d的同色最长等差数列,买下所有物品。让你给这个位置染成t种颜色中的一种(你来指定),其他位置会随机染成t种颜色之一,并保证这n-1个物品中第j种颜色的恰好有c[j]个。求最小期望花费保留四位小数。

注意询问相互独立,询问不会买走物品。

1<=n,m<=10^5,∑t<=2*10^5。

首先我们考虑t=1的情况,这样我们就要找到所有mod d与k同余的数之和。

这是一个经典问题了,把d对于sqrt(n)分类,小于sqrt(n)的修改时直接处理,大于sqrt(n)的查询时直接暴力。

那么我们考虑,要使花的钱最少,你选择的肯定是出现概率最少的颜色,设它有c个。

那么我们考虑一个对答案有贡献的位置k±pd,只有k+d,k+...这p个都是颜色c这个位置才对答案有贡献,即n-1个中指定p个同色的概率。

考虑这样染色的方案数,那么剩下n-1-p个只能有c-p个为这个颜色,方案数就是C(n-1-p,c-p),而概率就是C(n-1-p,c-p)/C(n-1,c)。

设这个概率为f(p),那么f(p)=f(p-1)*(c-p+1)/(n-p)。(自己推啊)

然后最坑的地方到了...注意到t>1时由抽屉原理,c<=(n-1)/2,那么(c-p+1)/(n-p)<=((n-1)/2-p+1)/(n-p)=(0.5n-p+0.5)/(n-p)。

我们随手推一推:(0.5n-p+0.5)/(n-p)<0.5⇔0.5n-p+0.5<0.5n-0.5p⇔p>1。

所以f(p)是呈指数级递减的!那么p大于一定范围的时候我们就可以直接忽略f(p)。

大概取个100显然就够了,于是我们暴力算这个东西,大于100就退出。

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <string>
#include <bitset>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <sstream>
#include <stack>
#include <iomanip>
using namespace std;
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define ll long long
#define ld double
#define vi vector<int>
#define fi first
#define se second
#define fe first
int n,m,v[233333],cs[233333];
int sum[666][666],S,P=123;
ld p[2333];
int main()
{
freopen("lzz.in","r",stdin);
freopen("lzz.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",v+i);
S=max(int(sqrt(n)),1);
for(int i=1;i<=S;i++)
{
for(int j=1;j<=n;j++) sum[i][j%i]+=v[j];
}
while(m--)
{
int s;
scanf("%d",&s);
if(s==1)
{
int a,b;
scanf("%d%d",&a,&b);
for(int i=1;i<=S;i++) sum[i][a%i]+=b-v[a];
v[a]=b; continue;
}
int t,k,d,c=2000000000;
scanf("%d%d%d",&t,&k,&d);
for(int i=1;i<=t;i++) scanf("%d",cs+i), c=min(c,cs[i]);
if(t==1)
{
if(d<=s) printf("%.4lf\n",(double)sum[d][k%d]);
else
{
ld rp=0;
for(int s=k;s<=n;s+=d) rp+=v[s];
for(int s=k-d;s>0;s-=d) rp+=v[s];
printf("%.4lf\n",rp);
}
continue;
}
p[0]=1;
for(int i=1;i<=P;i++)
if(i>c) p[i]=0; else p[i]=p[i-1]*(c-i+1)/(n-i);
ld ans=0;
for(int s=k,t=0;s<=n&&t<=P;s+=d,++t) ans+=v[s]*p[t];
for(int s=k-d,t=1;s>0&&t<=P;s-=d,++t) ans+=v[s]*p[t];
printf("%.4lf\n",ans);
}
}

B. 访问计划

一棵n个点有边权的树,现在要从根节点出发遍历每条边并返回根节点,沿路行走的花费为边权,此外可以使用不超过k次传送门,每次花费c元跳到任意一个节点。求最小花费。

1<=n,k<=2000,多组数据,∑n<=10000,答案在int范围内。

首先每条树边只会经过1或2次,这个似乎十分显然,证明可以用欧拉回路的判定来证。

而传送相当于是添加了一些能且仅能经过一次的边,那么每条边走过的奇偶性与该字数内新加顶点奇偶性相同,因为没有传送因为要来回必然是偶数,两个顶点都在子树内的传送对这条边没有意义,有一次传送就会是奇数。

所以(fa[x],x)这条边会经过2-(x子树内新加点个数)%2次。

那么我们只要记f[a][b]为a子树内有b个新加顶点的代价,直接树上背包转移即可。

由jsoi2016那题的证明这样做是O(n^2)的(我不会证啊qaq)

最后显然用f[1][2x]+x*c更新答案即可。

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <string>
#include <bitset>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <sstream>
#include <stack>
#include <iomanip>
using namespace std;
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define ll long long
#define ld double
#define vi vector<int>
#define fi first
#define se second
#define fe first
#define SZ 666666
int n,k,c,fst[SZ],vb[SZ],vc[SZ],nxt[SZ],M=0;
void ad_de(int a,int b,int c)
{
++M; nxt[M]=fst[a]; fst[a]=M;
vb[M]=b; vc[M]=c;
}
void gmin(int& x,int y)
{
if(x>y) x=y;
}
int siz[SZ],cst[2005][2005],tmp[2005];
void dp(int x,int f)
{
siz[x]=cst[x][0]=0;
for(int e=fst[x];e;e=nxt[e])
{
int b=vb[e]; if(b==f) continue;
dp(b,x);
memset(tmp,127/3,(siz[x]+siz[b]+1)*sizeof(int));
for(int p=0;p<=siz[x];p++)
{
for(int q=0;q<=siz[b];q++)
gmin(tmp[p+q],cst[x][p]+cst[b][q]+vc[e]*(2-(q&1)));
}
siz[x]+=siz[b];
for(int i=0;i<=siz[x];i++) cst[x][i]=tmp[i];
}
cst[x][++siz[x]]=1000000000;
for(int i=siz[x];i>=1;i--) gmin(cst[x][i],cst[x][i-1]);
}
int main()
{
freopen("mzz.in","r",stdin);
freopen("mzz.out","w",stdout);
while(scanf("%d%d%d",&n,&k,&c)!=EOF)
{
M=0; for(int i=1;i<=n;i++) fst[i]=0;
for(int i=1;i<n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
++a; ++b;
ad_de(a,b,c); ad_de(b,a,c);
}
dp(1,0);
int ans=2000000000;
for(int i=0;i<=k&&i+i<=n;i++)
gmin(ans,cst[1][i+i]+i*c);
printf("%d\n",ans);
}
}

C. 模范学长

给一个n*n的矩阵,矩阵的每个元素为一个多元多项式,问行列式合并同类项后是否每一项系数都是偶数。多项式中的参数为26个字母。

这题好神啊...

首先由Schwartz-Zippel定理(https://en.wikipedia.org/wiki/Schwartz%E2%80%93Zippel_lemma)。

一个域(定义域和值域)为有限域S的d次非零多项式,随机选择每个参数的值带入,把它的值误判为0的概率不超过d/|S|。

那么我们考虑多次随机找一些值带进去,计算行列式,计算它的值是否为0?

那么我们就要找到一个域和一些运算使得合并同类项完系数是偶数就意味着值为0。即满足在此域下x+x=0。

mod 2的域显然太小了误判概率十分高啊。

最神的地方就是:我们模上一个系数模2意义下的多项式!

由于系数在模2意义下是0/1,我们只要用一个二进制数来表示这个多项式就行了。

我们考虑这个域上的加减法,就相当于直接异或。

而一个多项式a模上这个多项式b,只要让a=min(a,a^b)即可。

为什么呢?因为a^b即为b-a,而如果b最高一位a在该位也为1,那么a^b就会小于a,那么我们就实现了取模操作。

那么我们乘法就可以倍增地进行,随机若干次,每次选择一个随机多项式带入26个变量,高斯消元计算行列式即可。

全是套路...

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <string>
#include <bitset>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <sstream>
#include <stack>
#include <iomanip>
using namespace std;
#define pb push_back
#define mp make_pair
typedef pair<int,int> pii;
typedef long long ll;
typedef double ld;
typedef vector<int> vi;
#define fi first
#define se second
#define fe first
int xors=647029825;
int mul(int a,int b)
{
int ans=0;
while(b)
{
if(b&1) ans=ans^a;
a<<=1; a=min(a,xors^a); b>>=1;
}
return ans;
}
#define SZ 666666
int val[SZ];
int gv(char* s)
{
int ans=0,cur=1;
while(*s)
{
if(*s=='+') ans^=cur, cur=1;
else if(isalpha(*s)) cur=mul(cur,val[*s-'a']);
else cur=*s-'0';
++s;
}
return ans^=cur;
}
int rndv()
{
int s=0;
for(int i=1;i<=40;i++) s=s*2333+rand()%2333;
if(s<0) s=-s;
s=min(s,s^xors);
return s;
}
int n,a[103][103];
char str[55][55][103];
bool gauss()
{
for(int i=1;i<=n;i++)
{
int p=0;
for(int j=i;j<=n;j++)
{
if(a[j][i]) {p=j; break;}
}
if(!p) return 1;
for(int j=i;j<=n;j++)
swap(a[i][j],a[p][j]);
int x=a[i][i];
for(int j=i+1;j<=n;j++)
{
int y=a[j][i]; if(!y) continue;
for(int k=i;k<=n;k++)
a[j][k]=mul(a[j][k],x)^mul(a[i][k],y);
}
}
return 0;
}
int main()
{
freopen("rzz.in","r",stdin);
freopen("rzz.out","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%s",str[i][j]);
a[i][j]=gv(str[i][j]);
}
}
bool ok=1;
for(int g=1;g<=20;g++)
{
for(int i=0;i<26;i++) val[i]=rndv();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++) a[i][j]=gv(str[i][j]);
}
ok=gauss();
if(!ok) break;
}
if(ok) puts("Yes"); else puts("No");
}
}

十连测Day1 题解的更多相关文章

  1. ZROI 提高十连测 Day1

    第一天的提高模拟测 考前特意睡了20min 还是歇菜了,果然自己菜是真实的. 题目质量海星 但是我都不会这是真的...题目由于是花钱买的这里就不放了 LINK:problem 熟悉我的人应该都知道账号 ...

  2. 正睿OI提高组十连测 day1 总结

    可能是最简单的一场比赛了吧,结果却打得这么差... T1是个找规律题,结果一开始愚蠢地找错了规律,然后又对拍,到1h多一点才过掉 然后看t2和t3,以为t2是个水题,t3也只要处理一下就好了,先写t2 ...

  3. bzoj 5216 [Lydsy2017省队十连测]公路建设 线段树维护 最小生成树

    [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 93  Solved: 53[Submit][Status][ ...

  4. ZROI2019 提高十连测

    额 掰手指头一数 特么又是第三年十连测了= = 2017一场没打 那时候好像一场比赛也就100人左右 2018前几场还都好好补了 后来开始放飞自我了 这时候一场有150人还多了 2019想让今年的No ...

  5. Lydsy2017省队十连测

    5215: [Lydsy2017省队十连测]商店购物 可能FFT学傻了,第一反应是前面300*300背包,后面FFT... 实际上前面背包,后面组合数即可.只是这是一道卡常题,需要注意常数.. //A ...

  6. THUSC2017 Day1题解

    THUSC2017 Day1题解 巧克力 题目描述 "人生就像一盒巧克力,你永远不知道吃到的下一块是什么味道." 明明收到了一大块巧克力,里面有若干小块,排成n行m列.每一小块都有 ...

  7. bzoj 5216: [Lydsy2017省队十连测]公路建设

    5216: [Lydsy2017省队十连测]公路建设 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 66  Solved: 37[Submit][St ...

  8. 提高十连测day3

    提高十连测day3 A 我们可以枚举两个 $ 1 $ 之间的相隔距离,然后计算形如 $ 00100100 \cdots $ 的串在原串中最⻓⼦序列匹配即可,复杂度 $ O(n^2) $ .寻找 $ S ...

  9. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

随机推荐

  1. 2016 ICPC大连站---F题 Detachment

    题意:输入一个x,将x拆分成一些小的数(这些数不能相同,即x=a1+a2+......   ai!=aj when i!=j),然后这些数相乘得到一个成积(s=a1*a2*......),求最大的乘积 ...

  2. kail linux 虚拟机安装实录(一) 新建虚拟机

    各位晚上好. 现在开始进行kail linux 在虚拟机上的安装. 我所使用的工具如下: kail linux 2.0   x64  http://mirrors.neusoft.edu.cn/kal ...

  3. iOS之清除缓存

    //清除缓存按钮的点击事件 - (void)putBufferBtnClicked:(UIButton *)btn{ CGFloat size = [self folderSizeAtPath:NSS ...

  4. AFNetworking 3.0 断点续传 使用记录

    最近项目中用到了压缩包下载,使用AFNetworking 3.0 下载压缩包 支持断点续传 代码如下: #import "HDInternet_handler.h" #import ...

  5. iOS---stringByAddingPercentEscapesUsingEncoding:' is deprecated: first deprecated in iOS 9.0 - Use -stringByAddingPercentEncodingWithAllowedCharacters: instead,

    旧方法 NSString *encoded = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; iOS9   ...

  6. (转)[原] Android 自定义View 密码框 例子

    遵从准则 暴露您view中所有影响可见外观的属性或者行为. 通过XML添加和设置样式 通过元素的属性来控制其外观和行为,支持和重要事件交流的事件监听器 详细步骤见:Android 自定义View步骤 ...

  7. select、poll、epoll区别总结

    1 本质上都是同步I/O 三者都是I/O复用,本质上都属于同步I/O.因为三者只是负责通知应用程序什么时候数据准备好了,实际的I/O操作还是在由应用程序处理:如果是异步I/O的话,实际I/O由内核处理 ...

  8. CRLF line terminators导致shell脚本报错:command not found

    Linux和Windows文本文件的行结束标志不同.在Linux中,文本文件用"/n"表示回车换行,而Windows用"/r/n"表示回车换行.有时候在Wind ...

  9. Shell : debug

    调试shell脚本的方法: 使用命令:sh -x yourShell.sh

  10. Java虚拟机栈

    Java Virtual Machine Stacks,线程私有,生命周期与线程相同,描述的是Java方法执行的内存模型:每一个方法执行的同时都会创建一个栈帧(Stack Frame),由于存储局部变 ...