Codeforces Round #463
A - Palindromic Supersequence
/*
题目大意:给出一个串,构造一个包含该串的回文串
*/
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=10010;
char s[N];
int main(){
scanf("%s",s);
int n=strlen(s);
for(int i=n-1;i;i--)printf("%c",s[i]);
for(int i=0;i<n;i++)printf("%c",s[i]);
puts(""); return 0;
}
B - Recursive Queries
/*
题目大意:定义F函数为一个数所有数字的乘积,定义G函数为分段函数,
当x小于10时为其本身,否则G(x)=G(F(x)),求区间有多少数G函数值为k
*/
#include <cstdio>
#include <algorithm>
using namespace std;
int T,l,r,k,sum[10][1000010],f[1000010];
int cal(int x){
int ans=1;
while(x)ans=x%10?ans*(x%10):ans,x/=10;
return ans;
}
int main(){
for(int i=0;i<10;i++)f[i]=i;
for(int i=10;i<=1000000;i++)f[i]=f[cal(i)];
for(int i=1;i<=1000000;i++){
for(int j=0;j<10;j++)sum[j][i]=sum[j][i-1];
sum[f[i]][i]++;
}
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",sum[k][r]-sum[k][l-1]);
}
return 0;
}
C - Permutation Cycle
/*
题目大意:求一个排列,使得其能被分解为大小为a或者b的置换
*/
#include <cstdio>
#include <algorithm>
using namespace std;
int n,a,b,p=1;
int main(){
scanf("%d%d%d",&n,&a,&b);
for(int i=0;i*a<=n;i++){ // !!!注意循环从0开始
if((n-i*a)%b==0){
int A=i,B=(n-i*a)/b;
for(int j=1;j<=A;j++){
for(int k=1;k<a;k++)printf("%d ",p+k);
printf("%d ",p); p+=a;
}
for(int j=1;j<=B;j++){
for(int k=1;k<b;k++)printf("%d ",p+k);
printf("%d ",p); p+=b;
}
return 0;
}
}puts("-1");
return 0;
}
D - Tree
/*
题目大意:开始给出只有一个节点的树,要求维护两个操作:
1.往树上增加一个叶节点,连在R上,且质量为W
2.寻找一个从R开始的最长数列满足,质量和不超过X,所有项为R的祖先,
对于数列中相邻的项i,j,后项i为前项j的祖先,有w[i]大于w[j]
并且在i到j的路径中不存在大于w[j]的点
题解:考虑到下一项是跳到祖先链上第一个比其大的位置,因此我们每次插入节点的时候,
直接将其插入到祖先链上第一个比其大的位置,查询的时候直接查询总和不超过X的最长链即可,
因为祖先的质量单调递增,总质量和单调递增,我们可以在树上倍增查找
*/
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N=400010,K=20;
int tot;
LL w[N],f[N][K],W[N][K];
void link(int x,int y){
f[x][0]=y;
W[x][0]=w[x];
for(int k=0;k<K-1;k++){
y=f[x][k];
if(y==-1)continue;
f[x][k+1]=f[y][k];
W[x][k+1]=W[x][k]+W[y][k];
}
}
int sf(int x,LL wx){
if(w[x]>=wx)return x;
for(int k=K-1;~k;k--){
if(f[x][k]<=0)continue;
if(w[f[x][k]]<wx)x=f[x][k];
}return f[x][0];
}
void init(){
for(int i=0;i<N;i++)
for(int k=0;k<K;k++)f[i][k]=-1;
f[tot=1][0]=0;
}
LL query(int x,LL wx){
LL res=0;
for(int k=K-1;~k;k--){
if(f[x][k]==-1||W[x][k]>wx)continue;
wx-=W[x][k]; res+=1<<k;
x=f[x][k];
}return res;
}
int q,op;
LL R,X,ans=0;
int main(){
init();
scanf("%d",&q);
while(q--){
scanf("%d%lld%lld",&op,&R,&X);
R^=ans,X^=ans;
if(op==1){
w[++tot]=X;
link(tot,sf(R,X));
}else printf("%lld\n",ans=query(R,X));
}
return 0;
}
E - Team Work
/*
题目大意:求ΣC(n,i)*i^k,n<=10^9,k<=5000
题解:利用第二类斯特林数公式进行代换
ΣC(n,i)*i^k=ΣC(n,i)*(ΣS(k,j)*P(i,j))
=ΣC(n,i)*(ΣS(k,j)*j!*C(i,j))
=ΣS(k,j)*j!*ΣC(n,i)*C(i,j)
=ΣS(k,j)*Σ(n!/((n-i)!*(i-j)!))
=ΣS(k,j)*P(n,j)*ΣC(n-j,n-i)
=ΣS(k,j)*P(n,j)*2^(n-j)
*/
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long LL;
const int mod=1000000007;
const int inv2=mod/2+1;
int n,k,S[5010];
int pow(LL a,int b,int m){LL t=1;for(;b;b>>=1,a=a*a%m)if(b&1)t=t*a%m;return t;}
void CalS(){S[1]=1;for(int i=2;i<=k;i++)for(int j=i;j;j--)S[j]=(1LL*S[j]*j+S[j-1])%mod;}
int main(){
scanf("%d%d",&n,&k); CalS();
int P=1,M=pow(2,n,mod),ans=0;
for(int i=1;i<=k;i++){
P=1LL*P*(n-i+1)%mod;
M=1LL*M*inv2%mod;
ans=(1LL*ans+1LL*S[i]*P%mod*(LL)M%mod)%mod;
}printf("%d\n",ans);
return 0;
}
F - Escape Through Leaf
/*
题目大意:给出一棵树,树的根为1,树上每个节点有两个值a和b,
从一个节点i可以跳到子树上任意一个节点j,代价是a[i]*b[j],
从一个点到达另一个节点的代价是图中所有代价之和,
问每个节点跳到任意一个叶节点的代价最小为多少。
题解:我们递归计算答案,对于每个节点来说,他的答案为min(a[i]*b[j]+ans[j]),
那么我们对于每个节点维护一个子树的动态凸包,求最大mx+b即可
为避免过多的插入和比较,我们把信息都保存在节点最大子树的代表节点u[x]中,
通过只改变标记u[x]以替代信息的大量转移。
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL is_query=-(1LL<<62);
struct Line{
LL m,b;
mutable function<const Line *()> succ;
bool operator<(const Line &rhs)const{
if(rhs.b!=is_query)return m<rhs.m;
const Line *s=succ();
if(!s)return 0;
LL x=rhs.m;
return b-s->b<(s->m-m)*x;
}
};
struct HullDynamic:public multiset<Line>{
bool check(iterator y) {
auto z=next(y);
if(y==begin()){
if(z==end())return 0;
return y->m==z->m&&y->b<=z->b;
}
auto x=prev(y);
if(z==end())return y->m==x->m&&y->b<=x->b;
return (x->b-y->b)*(long double)(z->m-y->m)>=(y->b-z->b)*(long double)(y->m-x->m);
}
void insert_line(LL m,LL b){
auto y=insert({m,b});
y->succ=[=]{return next(y)==end()?0:&*next(y);};
if(check(y)){erase(y);return;}
while(next(y)!=end()&&check(next(y)))erase(next(y));
while(y!=begin()&&check(prev(y)))erase(prev(y));
}
LL query(LL x){
auto l=*lower_bound((Line){x,is_query});
return l.m*x+l.b;
}
};
const int N=100010;
int n,a[N],b[N],size[N],u[N],res[N],st[N],en[N];
vector<int> g[N];
LL ans[N];
HullDynamic T[N];
int dfn=0;
void dfs(int x,int fx){
st[x]=++dfn;
res[dfn]=x;
int t=-1; size[x]=1;
for(int y:g[x]){
if(y==fx)continue;
dfs(y,x);
size[x]+=size[y];
if(t==-1||size[y]>size[t])t=y;
}
if(t==-1){
T[x].insert_line(-b[x],0);
ans[x]=0;
u[x]=x;
}
else{
u[x]=u[t];
for(int y:g[x])if(y!=t){
for(int i=st[y];i<=en[y];i++)T[u[x]].insert_line(-b[res[i]],-ans[res[i]]);
}
ans[x]=-T[u[x]].query(a[x]);
T[u[x]].insert_line(-b[x],-ans[x]);
}en[x]=dfn;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",a+i);
for(int i=1;i<=n;i++)scanf("%d",b+i);
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}dfs(1,0);
for(int i=1;i<=n;i++)printf("%lld ",ans[i]);
return 0;
}
G - Palindrome Partition
/*
题目大意:给出一个串s,现在要求将其划分子串,并且划分结果呈回文
求方案数,如abcdabcd划分为ab,cd,cd,ab,为回文。
题解:我们将串后半部分倒序依次插入前半部分的后面,比如abcdcdab,
将构成abbacddc,那么问题就转化为新串能拆分成回文子串的方案数,
我们对新串边构建回文自动机,并在构建的同时计算答案,
diff数组表示节点与其失配位置最长后缀回文的差值,
记anc为将连续相同差值去除后的祖先节点,比如abbabbabba,
在去除连续相同差值abb之后,得到祖先节点a,
则对于一种差值长度的答案来说,若失配位置为其祖先节点,则答案等于失配节点的答案
否则其值为拿掉祖先节点加一倍差值之后的位置的答案ans,加上其失配节点的答案g,
对于不同差值长度的节点答案g累积到当前位置答案ans上去,
最后输出结尾位置的答案即可。
*/
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=1000010;
const int mod=1000000007;
int n,cnt,lst,s[N],l[N],f[N],diff[N],anc[N],g[N],ans[N],a[N][26];
char S[N];
void add(int &x,int y){if((x+=y)>=mod)x-=mod;}
void init(){lst=cnt=1;f[0]=1,f[1]=0;l[1]=-1;}
void extend(int np,int c){
int p=lst;
while(s[np]!=s[np-l[p]-1])p=f[p];
if(!a[p][c]){
int x=++cnt,fp=f[p];
while(s[np]!=s[np-l[fp]-1])fp=f[fp];
l[x]=l[p]+2;
f[x]=a[fp][c];
a[p][c]=x;
diff[x]=l[x]-l[f[x]];
anc[x]=diff[x]==diff[f[x]]?anc[f[x]]:f[x];
}lst=a[p][c];
}
int main(){
scanf("%s",S+1);
n=strlen(S+1);
for(int i=1;i*2<=n;i++){
s[i*2-1]=S[i]-'a';
s[i*2]=S[n-i+1]-'a';
}s[0]=-1; ans[0]=1; init();
for(int i=1;i<=n;i++){
extend(i,s[i]);
for(int x=lst;x;x=anc[x]){
g[x]=ans[i-l[anc[x]]-diff[x]];
if(anc[x]!=f[x])add(g[x],g[f[x]]);
if(i%2==0)add(ans[i],g[x]);
}
}printf("%d\n",ans[n]);
return 0;
}
Codeforces Round #463的更多相关文章
- Codeforces Round #463 F. Escape Through Leaf (李超线段树合并)
听说正解是啥 set启发式合并+维护凸包+二分 根本不会啊 , 只会 李超线段树合并 啦 ... 题意 给你一颗有 \(n\) 个点的树 , 每个节点有两个权值 \(a_i, b_i\) . 从 \( ...
- ICM Technex 2018 and Codeforces Round #463 (Div. 1 + Div. 2, combined) A
2018-02-19 A. Palindromic Supersequence time limit per test 2 seconds memory limit per test 256 mega ...
- ICM Technex 2018 and Codeforces Round #463 (Div. 1 + Div. 2, combined)
靠这把上了蓝 A. Palindromic Supersequence time limit per test 2 seconds memory limit per test 256 megabyte ...
- Codeforces 932 C.Permutation Cycle-数学 (ICM Technex 2018 and Codeforces Round #463 (Div. 1 + Div. 2, combined))
C. Permutation Cycle time limit per test 2 seconds memory limit per test 256 megabytes input stand ...
- Codeforces 932 B.Recursive Queries-前缀和 (ICM Technex 2018 and Codeforces Round #463 (Div. 1 + Div. 2, combined))
B. Recursive Queries time limit per test 2 seconds memory limit per test 256 megabytes input stand ...
- Codeforces 932 A.Palindromic Supersequence (ICM Technex 2018 and Codeforces Round #463 (Div. 1 + Div. 2, combined))
占坑,明天写,想把D补出来一起写.2/20/2018 11:17:00 PM ----------------------------------------------------------我是分 ...
- 【ICM Technex 2018 and Codeforces Round #463 (Div. 1 + Div. 2, combined) D】Tree
[链接] 我是链接,点我呀:) [题意] 让你在树上找一个序列. 这个序列中a[1]=R 然后a[2],a[3]..a[d]它们满足a[2]是a[1]的祖先,a[3]是a[2]的祖先... 且w[a[ ...
- 【ICM Technex 2018 and Codeforces Round #463 (Div. 1 + Div. 2, combined) C】 Permutation Cycle
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] p[i] = p[p[i]]一直进行下去 在1..n的排列下肯定会回到原位置的. 即最后会形成若干个环. g[i]显然等于那个环的大 ...
- 【ICM Technex 2018 and Codeforces Round #463 (Div. 1 + Div. 2, combined) B】Recursive Queries
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 写个记忆化搜索. 接近O(n)的复杂度吧 [代码] #include <bits/stdc++.h> using nam ...
随机推荐
- Struts2笔记1:--Struts2原理、优点、编程流程、6大配置文件以及核心配置文件struts.xml
Struts2原理(底层使用的是Servlet的doFilter方法): Struts2优点: 第一个Struts程序: 在开发Struts程序之前,首先要导入额外的jar包,基本需求的是14个jar ...
- 01-Coredump核心转存&&Linux程序地址分析【转】
转自:http://www.itwendao.com/article/detail/404132.html 目录(?)[-] 一Core Dump核心转存 二Linux程序地址分析 一Core Dum ...
- LINUX修改、增加IP的方法,一张网卡绑定多个IP/漂移IP【转】
临时增加IP命令:ifconfig eth0:1 ip地址 netmask 子网码 broadcast 广播地址 gateway 网关 ifconfig eth0:1 10.1.104.65 net ...
- Prepare tasks for django project deployment.md
As we know, there are some boring tasks while deploy Django project, like create db, do migrations a ...
- samba和SELINUX 冲突
在使用Samba进行建立Window与Linux共享时,要是不能访问,出现“您可能没有权限使用网络资源”. setsebool -P samba_enable_home_dirs on setsebo ...
- Java项目打war包的方法
我们可以运用DOS命令来手工打war包: 首先,打开DOS命令行,敲入“jar”,我们发现它提示不是内部或外部的命令这样的错误,这时八成是你的JAVA环境没有配置好,我们可以用JAVA_HOME方式或 ...
- 修饰符(动态String数组篇)--- 常用 解除疑问。
1.无修饰符----是直接传基本类型的地址过来,并没有把基本类型的指针复制一份入栈,所以一旦修改就是修改原来的值. 2.const 修饰符 与 无修饰符一致. 3.var修饰符 与 上一致. 4.ou ...
- linux用户操作
1.用户种类 Linux具有三种用户: 超级管理员root:具有最高权限,UID=0 GID=0伪用户(System Account):(UID=1~499)普通用户(login-Account): ...
- Codeforces 429B Working out(递推DP)
题目链接:http://codeforces.com/problemset/problem/429/B 题目大意:两个人(假设为A,B),打算健身,有N行M列个房间,每个房间能消耗Map[i][j]的 ...
- (三)Jsoup 使用选择器语法查找 DOM 元素
第一节: Jsoup 使用选择器语法查找 DOM 元素 Jsoup使用选择器语法查找DOM元素 我们前面通过标签名,Id,Class样式等来搜索DOM,这些是不能满足实际开发需求的, 很多时候我们需要 ...