A.All X
题目:
http://acm.hdu.edu.cn/showproblem.php?pid=5690
题意:
F(x,m) 代表一个全是由数字x组成的m位数字。请计算,以下式子是否成立:
F(x,m) mod k ≡ c
思路:
k小于1e4,所以取模得到的结果不会多,直接暴力出循环节判断就行了。
代码:
//kopyh
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define N 11234
using namespace std;
long long n,m,sum,res,flag;
long long a[N];
int main()
{
long long i,j,k,cas,T,t,x,y,z,c;
scanf("%I64d",&T);
cas=0;
while(T--)
{
scanf("%I64d%I64d%I64d%I64d",&x,&m,&k,&c);
sum=0;
t=x; y=1;
while(t<k)t*=10,t+=x,y++;
if(y>=m)
{
y=0;
while(m--)y*=10,y+=x;
printf("Case #%I64d:\n",++cas);
printf(y%k==c?"Yes\n":"No\n");
continue;
}
m-=y;m++;
t%=k;
memset(a,0,sizeof(a));
while(!a[t])
{
a[t]=++sum;
t*=10;t+=x;
t%=k;
}
m%=sum;
if(!m)m=sum;
t=-1;
for(i=0;i<N;i++)if(a[i]==m)t=i;
printf("Case #%I64d:\n",++cas);
printf(t==c?"Yes\n":"No\n");
}
return 0;
}
B.Sitting in Line
题目:
http://acm.hdu.edu.cn/showproblem.php?pid=5691
题意:
给出一列数字,其中有的数字的位置是不固定的,找到重新排列之后的相邻数字乘积之和最小的结果。
思路:
不超过16个数字,直接数位dp判断已用的数字,然后一位一位往后枚举就行了。
代码:
//kopyh
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f3f3f3f3f
#define MOD 1000000007
#define N 16
using namespace std;
long long n,m,sum,res,flag;
long long a[N],b[N],dp[1<<16][16];
int main()
{
long long i,j,k,cas,T,t,x,y,z;
scanf("%d",&T);
cas=0;
while(T--)
{
scanf("%I64d",&n);
for(i=0;i<n;i++)scanf("%I64d%I64d",&a[i],&b[i]);
for(i=0;i<(1<<n);i++)for(j=0;j<n;j++)dp[i][j]=-INF;
for(unsigned int i=0;i<(1<<n);i++)
for(j=0;j<n;j++)
if(dp[i][j]!=-INF||__builtin_popcount(i)==0)
for(k=0;k<n;k++)
if(!((1<<k)&i) && (b[k]==-1||b[k]==__builtin_popcount(i)))
dp[(1<<k)|i][k] = max(dp[(1<<k)|i][k],dp[i][j]!=-INF?dp[i][j]+a[j]*a[k]:0);
res=-INF;
for(i=0;i<n;i++)res=max(res,dp[(1<<n)-1][i]);
printf("Case #%I64d:\n%I64d\n",++cas,res);
}
return 0;
}
C.Snacks
题目:
http://acm.hdu.edu.cn/showproblem.php?pid=5692
题意:
一棵树上每个节点都有价值,求从起点0经过某个节点的总价值和最大的路径,两种操作,0:改变一个节点的价值,1:找到经过某节点的最优路径
思路:
对于一棵树只要处理出起点到每个节点的价值和,然后每次询问就是找对应节点为根的子树中的最大值,修改就是对应子树全部变化,很明显直接dfs序然后预处理就行了。
代码:
//kopyh
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f3f3f3f3f
#define MOD 1000000007
#define N 212345
using namespace std;
long long n,m,res,flag;
vector<long long>g[N];
long long val[N],sum[N];
long long a[N],l[N],r[N];
void init()
{
for(int i=0;i<n;i++)g[i].clear();
}
#define root 1 , n , 1
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
struct node
{
long long pos,val;
node(long long x=0,long long y=0){pos=x,val=y;}
friend bool operator < (node a, node b)
{
return a.val < b.val;
}
}arr[N<<2];
long long add[N<<2],tot;
void pushUp(long long rt)
{
arr[rt] = max(arr[rt<<1],arr[rt<<1|1]);
}
void pushDown(long long l,long long r,long long rt)
{
if(add[rt])
{
long long m = (l+r)>>1;
add[rt<<1] += add[rt];
add[rt<<1|1] += add[rt];
arr[rt<<1].val += add[rt];
arr[rt<<1|1].val += add[rt];
add[rt] = 0;
}
}
void updata(long long l,long long r,long long rt,long long ql,long long qr,long long val)
{
if(l>qr||ql>r)return;
if(l>=ql&&r<=qr)
{
arr[rt].val += val;
add[rt] += val;
return;
}
pushDown(l,r,rt);
long long m = (l+r)>>1;
if(ql<=m)updata(lson,ql,qr,val);
if(qr>m)updata(rson,ql,qr,val);
pushUp(rt);
}
void build(long long l,long long r,long long rt)
{
add[rt]=0;
if(l == r)
{
arr[rt].val = sum[a[++tot]];
arr[rt].pos = tot;
return;
}
long long m = (l+r)>>1;
build(lson);
build(rson);
pushUp(rt);
}
node query(long long l,long long r,long long rt,long long ql,long long qr)
{
if(l>qr||ql>r)
return node(-INF,-INF);
if(l>=ql&&r<=qr)
return arr[rt];
pushDown(l,r,rt);
long long m = (l+r)>>1;
return max(query(lson,ql,qr),query(rson,ql,qr));
}
void dfs(long long pos, long long fa)
{
a[++tot]=pos;
l[pos]=tot+1;
for(int i=0;i<g[pos].size();i++)
{
if(g[pos][i]==fa)continue;
sum[g[pos][i]]=sum[pos]+val[g[pos][i]];
dfs(g[pos][i],pos);
}
r[pos]=tot+1;
}
int main()
{
long long i,j,k,cas,T,t,x,y,z;
scanf("%I64d",&T);
cas=0;
while(T--)
{
printf("Case #%I64d:\n",++cas);
scanf("%I64d%I64d",&n,&m);
init();
for(i=0;i<n-1;i++)
{
scanf("%I64d%I64d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}
for(i=0;i<n;i++)scanf("%I64d",&val[i]);
sum[0]=val[0];tot=-1;
dfs(0,0);
tot=-1;
build(root);
for(i=0;i<m;i++)
{
scanf("%I64d",&z);
if(z)
{
scanf("%I64d",&x);
printf("%I64d\n",query(root,l[x],r[x]).val);
}
else
{
scanf("%I64d%I64d",&x,&y);
updata(root,l[x],r[x],y-val[x]);
val[x]=y;
}
}
}
return 0;
}
D.Game
题目:
http://acm.hdu.edu.cn/showproblem.php?pid=5693
题意:
所有连续的等差数列并且差值在列表之中的能够删去,求删到最后最多能删去多少数。
思路:
典型区间dp,对于能够删去的数对预处理,然后区间dp跑就行了。
代码:
//kopyh
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define N 1123
using namespace std;
int n,m,sum,res,flag;
int a[N],d[N],b[N][N],dp[N][N];
int main()
{
int i,j,k,cas,T,t,x,y,z,len,l,r;
scanf("%d",&T);
cas=0;
while(T--)
{
scanf("%d%d",&n,&m);
memset(b,0,sizeof(b));
memset(dp,0,sizeof(dp));
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<=m;i++)
{
scanf("%d",&d[i]);
for(j=1;j<=n;j++)
for(k=j+1;k<=n;k++)
if(a[k]-a[j]==d[i])
b[j][k] = 1;
}
for(len=1;len<=n;len++)
for(l=1;l<=n-len;l++)
{
r=l+len;
dp[l][r]=max(dp[l][r-1],dp[l+1][r]);
if(b[l][r]&&dp[l+1][r-1]==(r-l-1))
dp[l][r] = max(dp[l][r],dp[l+1][r-1]+2);
for(i=l+1;i<r;i++)
{
dp[l][r] = max(dp[l][r],dp[l][i]+dp[i+1][r]);
if(b[l][i]&&b[i][r]&&a[i]-a[l]==a[r]-a[i]&&dp[l+1][i-1]==(i-l-1)&&dp[i+1][r-1]==(r-i-1))
dp[l][r] = max(dp[l][r],r-l+1);
}
}
printf("%d\n",dp[1][n]);
}
return 0;
}
E.BD String
题目:
http://acm.hdu.edu.cn/showproblem.php?pid=5694
题意:
S(1)=B
S(2)=BBD
S(3)=BBDBBDD
…
S(n)=S(n−1)+B+reverse(flip(S(n−1))
其中,reverse(s)指将字符串翻转,比如reverse(BBD)=DBB,flip(s)指将字符串中的B替换为D,D替换为B,比如flip(BBD)=DDB。
S(3)=BBDBBDD
…
S(n)=S(n−1)+B+reverse(flip(S(n−1))
其中,reverse(s)指将字符串翻转,比如reverse(BBD)=DBB,flip(s)指将字符串中的B替换为D,D替换为B,比如flip(BBD)=DDB。
求上面描述的字符串在L到R直接B的个数。
思路:
明显每个串的前后半段基本一致,除了中间处前半段为B后半段为D,所以可以直接递归求解。
代码:
//kopyh
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define N 61
using namespace std;
long long n,m,sum,res,flag;
long long b[N],d[N],len[N];
void init()
{
b[1]=len[1]=1;d[1]=0;
for(int i=2;i<N;i++)
b[i]=b[i-1]+d[i-1]+1,d[i]=d[i-1]+b[i-1],len[i]=len[i-1]*2+1;
}
long long solve(long long n)
{
if(n<=1)return n;
long long t = lower_bound(len,len+N,n)-len;
if(len[t]==n)return b[t];
return b[t-1]+1+solve(n-len[t-1]-1)-(n>=(len[t-1]+1)/2+1+len[t-1]);
}
int main()
{
init();
long long i,j,k,cas,T,t,x,y,z;
scanf("%I64d",&T);
cas=0;
while(T--)
{
scanf("%I64d%I64d",&x,&y);
printf("%I64d\n",solve(y)-solve(x-1));
}
return 0;
}
F.Gym Class
题目:
http://acm.hdu.edu.cn/showproblem.php?pid=5695
题意:
所有人排序,有的人会不想让某人站在他前面,每个人的评分是他前面还包括他自己的所有人序号的最小值,求可能的最大评价之和。
思路:
只要满足拓扑序的前提下尽可能的让序号大的人在前面就行了。
代码:
//kopyh
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define N 1123456
using namespace std;
int n,m,sum,res,flag;
vector<int>g[N];
priority_queue<int>q;
int a[N],b[N],tot;
int main()
{
int i,j,k,cas,T,t,x,y,z;
scanf("%d",&T);
cas=0;
while(T--)
{
scanf("%d%d",&n,&m);
memset(a,0,sizeof(a));
for(i=1;i<=n;i++)g[i].clear();
tot=0;
while(!q.empty())q.pop();
for(i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
g[x].push_back(y);
a[y]++;
}
for(i=1;i<=n;i++)if(!a[i])q.push(i);
while(!q.empty())
{
t=q.top();q.pop();
b[tot++]=t;
for(i=0;i<g[t].size();i++)
{
a[g[t][i]]--;
if(!a[g[t][i]])q.push(g[t][i]);
}
}
long long sum=0;t=INF;
for(i=0;i<n;i++)
{
t=min(t,b[i]);
sum+=t;
}
printf("%I64d\n",sum);
}
return 0;
}
本文解析了六道ACM竞赛编程题,包括全由特定数字组成的数列的模运算问题、数字排列组合以求最小相邻乘积和的问题、树形结构上的节点价值最大化路径问题、等差数列删除问题、特殊字符串中字符计数问题以及人员排序问题。
&spm=1001.2101.3001.5002&articleId=51510537&d=1&t=3&u=a3eb75e19b4147b99457461fdd0d8b30)
2824

被折叠的 条评论
为什么被折叠?



