Problem A 树状数组

给出数x,一直执行x = x and (x+1)-1 直到 x=0 为止 询问这个数执行运算的次数。

这个数以二进制的形式表述出 x = s1 & s2 .... s2 & s3 其中s2字段重复n次 &表示连接符号。

对于$100\%$的数据 $ length(s1),length(s2),length(s3) \leq 10^3 ,n \leq 10^6$

Sol : 这道题目就是求x+1中含有二进制1的个数。

不妨设x=A111...其中A表示一个偶数二进制数,其中后面1的个数可以是任意个。

x+1 = (A+1)000... 所以 x and (x+1) = (A and (A+1))000... = A000...

所以x and (x+1) -1 = (A-1)111...

可以发现最后的一串1其实是对最后答案没有影响的,所以直接删除即可。

由于每次会破坏且仅破坏A中的一个1。直接求出A中的1的个数即可。

比如 : 1111001100 一次只会破坏最后的0,然后把最低的一个1破坏,--> 1111001011->11110010(消掉末尾所有的1)

这等价于求A=x+1中含有二进制1的个数。

实现细节: 先求出总的1的个数,然后如果数的末尾有连续的1,那么在总的个数中减去即可。

复杂度: $O(T\times length(s1+s2+s3) )$

# pragma GCC optimize()
# include <bits/stdc++.h>
# define int long long
using namespace std;
const int N=1e5+;
char s1[N],s2[N],s3[N];
int n;
signed main()
{
int T; cin>>T;
while (T--) {
scanf("%s%s%s",s1,s2,s3);
scanf("%lld",&n);
int len1=strlen(s1),len2=strlen(s2),len3=strlen(s3);
int tot=;
for (int i=;i<len1;i++) if (s1[i]=='') tot++;
for (int i=;i<len2;i++) if (s2[i]=='') tot+=n;
for (int i=;i<len3;i++) if (s3[i]=='') tot++;
tot++;
for (int i=len3-;i>=;i--)
if (s3[i]=='') goto End;
else tot--;
for (int i=len2-;i>=;i--)
if (s2[i]=='') goto End;
else tot--;
tot-=len2*(n-);
for (int i=len1-;i>=;i--)
if (s1[i]=='') goto End;
else tot--;
End:printf("%lld\n",tot);
}
return ;
}

ftree.cpp

Problem B 运动会

m个运动员进行n项比赛,最终成绩为这n项比赛排名相加,现在已知某人的n项比赛的排名$x_i$

考虑等概率情况下,该人的总成绩排名期望值。(排名要求严格)

对于100%的数据$n\leq 100,m\leq 1000$

Sol : 这是一道动态规划的题目。

定义f[i][j] 表示前i项比赛,排名总和为j的单人期望概率。

考虑从第i项比赛获得第k名转移而来。

转移方程为 : $ f[i][j] = \sum\limits_{k=1,k\neq x_i}^{m} f[i-1][j-k] $

由于有m-1个人,对于每一个人其总成绩超过$\sum\limits_{i=1}^{n}x_i$ 总期望是 $(m-1)\times \sum\limits_{i=1}^{\sum\limits_{i=1}^{n}x_i -1} f[n][i] $

所以答案的期望排名就是  $1 + (m-1)\times \sum\limits_{i=1}^{\sum\limits_{i=1}^{n}x_i -1} f[n][i] $

然后使用前缀和优化,可以做到$O(mn^2)$

# pragma GCC optimize()
# include <bits/stdc++.h>
using namespace std;
const int N=,M=;
int n,m,x[N];
double f[N][N*M];
double s[N*M];
double t[N*M];
int main()
{
// freopen("meeting.in","r",stdin);
// freopen("meeting.out","w",stdout);
scanf("%d%d",&n,&m);
if (m==) { puts(""); return ;}
int ret=;
for (int i=;i<=n;i++) scanf("%d",&x[i]),ret+=x[i];
s[]=f[][]=;
for (int i=;i<=n*m;i++) s[i]=s[i-]+f[][i];
for (int i=;i<=n;i++) {
memset(t,,sizeof(t));
for (int j=;j<=n*m;j++) {
double sum=s[j-]-((j-m->=)?s[j-m-]:);
if (j-x[i]>=&&j-x[i]<=j-) sum-=f[i-][j-x[i]];
sum/=1.0*(m-);
f[i][j]+=sum;
t[j]=t[j-]+f[i][j];
}
memcpy(s,t,sizeof(t));
}
double ans=;
for (int j=;j<ret;j++) ans+=f[n][j];
printf("%.12lf\n",+ans*(m-));
return ;
}

meeting.cpp

Problem C 区间GCD

给出一个序列$\{a_n\}$要求维护$m$个操作 查询[l,r]区间GCD个数和在整个序列中的子序列GCD值为k的子序列数目。

对于100%的数据$n,m \leq 10^5 a_i \leq 10^9$

Sol : 显然对于求出区间gcd的询问用ST表就可以$O(\alpha n log_2 n)$预处理,然后$O(1)$ 求解。

考虑第二问的一个性质,任何首端固定区间[1,n]的gcd值单调不增而且种类至多为$log_2 n$ 个。

于是枚举首端位置,然后对于确定的首端,二分不断扩展后端点,找出这相同gcd的$log_2 n$ 子序列gcd,存入map中。

然后直接用$O(log_2 n log_2 log_2 n)$的代价直接映射即可。

这样做的复杂度是$O(\alpha n log^2_2 n + m log_2 n log_2 log_2 n )$

#pragma GCC optimize(2)
# include <bits/stdc++.h>
# define int long long
using namespace std;
const int N=1e5+;
int f[N][],n,m,a[N];
int LG[N<<];
map<int,int>mp;
int read(){
int x = ; int zf = ; char ch = ' ';
while (ch != '-' && (ch < '' || ch > '')) ch = getchar();
if (ch == '-') zf = -, ch = getchar();
while (ch >= '' && ch <= '') x = x * + ch - '', ch = getchar(); return x * zf;
}
int gcd(int x,int y)
{
if (y==) return x;
return gcd(y,x%y);
}
void buildST()
{
for (int i=;i<=n;i++) f[i][]=a[i];
int t=LG[n]+;
for (int j=;j<t;j++)
for (int i=;i<=n-(<<j)+;i++)
f[i][j]=gcd(f[i][j-],f[i+(<<(j-))][j-]);
}
int query(int l,int r)
{
int k=LG[r-l+];
return gcd(f[l][k],f[r-(<<k)+][k]);
}
void work(int pos)
{
int pt=pos;
while (pt<=n) {
int g=query(pos,pt);
int l=pt,r=n,ans;
while (l<=r) {
int mid=(l+r)>>;
if (query(pos,mid)==g) ans=mid,l=mid+;
else r=mid-;
}
mp[g]+=ans-pt+;
pt=ans+;
}
}
signed main()
{
int T=read();
while (T--) {
mp.clear(); n=read();
for (int i=;i<=n*;i++) LG[i]=log(i)/log();
for (int i=;i<=n;i++) a[i]=read();
buildST();
for (int i=;i<=n;i++) work(i);
m=read();
while (m--) {
int l=read(),r=read();
int t=query(l,r);
printf("%lld %lld\n",t,mp[t]);
}
}
return ;
}

gcd.cpp

HGOI 20190705 题解的更多相关文章

  1. HGOI 20181028 题解

    HGOI 20181028(复赛备考) /* 真是暴力的一天,最后一题MLE?由于数组开得太大了!!! 270滚粗 考场上好像智商高了很多?!(假的) */ sol:暴力求解,然后没有数据范围吐槽一下 ...

  2. HGOI 20190310 题解

    /* 又是又双叒叕WA的一天... 我太弱鸡了... 今天上午打了4道CF */ Problem 1 meaning 给出q组询问,求下列函数的值$ f(a) = \max\limits_{0 < ...

  3. HGOI 20190303 题解

    /* 记一串数字真难. 5435 今天比赛又是hjcAK的一天. 今天开题顺序是312,在搞T1之前搞了T3 昨天某谷月赛真是毒瘤. 但是讲评的同学不错,起码T4看懂了... 构造最优状态然后DP的思 ...

  4. HGOI 20180224 题解

    /* The Most Important Things: ljc chat with fyh on QQTa说期末考Ta数学74分感觉不好但是我觉得fyh是地表最强的鸭~~(of course en ...

  5. HGOI 20190218 题解

    /* 又是AK局... hjc又双叒叕AK了... Hmmm...我侥幸 */ Problem A card 给出无序序列a[]可以选择一个数插入到合适的位置作为一次操作,至少多少次操作后可以把序列变 ...

  6. HGOI 20190217 题解

    /* for me,开训第一天 /beacuse 文化课太差被抓去补文化课了... 看一眼题 : AK局? 但是,Wa on test #10 in problem C 290! (就差那么一咪咪) ...

  7. HGOI 20181103 题解

    problem:把一个可重集分成两个互异的不为空集合,两个集合里面的数相乘的gcd为1(将集合中所有元素的质因数没有交集) solution:显然本题并不是那么容易啊!考场上想了好久.. 其实转化为上 ...

  8. HGOI 20181101题解

    /* 又是爆0的一天(不知道今年高考难不难,反正今天(信息学)真的难!) */ solution:对于两个数相加,有一个显然的结论就是要么不进位(相对于位数大的),要么(进最多一位) 然后对于整个数组 ...

  9. HGOI 20191108 题解

    Problem A 新婚快乐 一条路,被$n$个红绿灯划分成$n+1$段,从前到后一次给出每一段的长度$l_i$,每走$1$的长度需要$1$分钟. 一开始所有红绿灯都是绿色的,$g$分钟后所有红绿灯变 ...

随机推荐

  1. Python字典推导式将cookie字符串转化为字典

    Python中的列表推导式一般是大家所熟悉的,可以极大的简洁代码:而Python中的字典推导式和列表推导式也是大同小异的 cookie: PHPSESSID=et4a33og7nbftv60j3v9m ...

  2. CSP 字符串匹配(201409-3)

    问题描述 给出一个字符串和多行文字,在这些文字中找到字符串出现的那些行.你的程序还需支持大小写敏感选项:当选项打开时,表示同一个字母的大写和小写看作不同的字符:当选项关闭时,表示同一个字母的大写和小写 ...

  3. AppCan调试问题

    来源:http://edu.appcan.cn/theVideoMain1.html?chapterId=248_1 第1步, 生成AppCan调试中心 第2步, 启动AppCan调试中心 第3步, ...

  4. js设计模式--发布订阅模式

    前言 本系列文章主要根据<JavaScript设计模式与开发实践>整理而来,其中会加入了一些自己的思考.希望对大家有所帮助. 概念 发布-订阅模式又叫观察者模式,它定义对象间的一种一对多的 ...

  5. JavaSE--异常机制

    异常就是程序在运行时出现的不正常情况.发生在运行时期,java程序在运行时期发生的不正常情况,此时java就按照面向对象的思想对不正常现象进行描述和对象的封装.异常的由来:问题也是现实生活中一个具体的 ...

  6. c# ListView 简单操作

    1. 添加数据 listView1.Items.Clear(); for (int i = 0; i < 50; i++) { ListViewItem lv = new ListViewIte ...

  7. Android Studio 配置Gradle总结

    一, 问题:①换个新电脑安装完Android Sutdio第一次打开一个工程巨慢怎么办? ② 手动配置Gradle Home为什么总是无效? ③ 明明已经下载了Gradle,配置了gradle hom ...

  8. 三剑客-awk(简写)

    特殊要点:$0 表示整个当前行$1 每行第一个字段NF 字段数量变量NR 每行的记录号,多文件记录递增OFS 输出字段分隔符, 默认也是空格,可以改为制表符等ORS 输出的记录分隔符,默认为换行符,即 ...

  9. TKmybatis和mybatisplus哪个好用

    文档连接 :http://baomidou.oschina.io/mybatis-plus-doc/#/?id=%E7%AE%80%E4%BB%8B https://gitee.com/hengboy ...

  10. 为SourceInsight添加多行注释功能菜单

    由于项目看代码主要使用的是Source Insight,习惯了其他编辑器的多行注释功能,对此感到很不习惯,查询网上程序,可以自行添加. 1.打开project,选择base项目中的utils.em,添 ...