hdu的题目,我挂到了VJ上
VJ链接: https://cn.vjudge.net/contest/165580#overview
hdoj链接:太长了 戳这里就好了
给妹子们出的题目,貌似没有那么凶。。但是渣渣也仅会7道题。。。
没有队友搅屎,个人切题的感觉还不错。。 也是把会的题都做了。。
这个D 虽然出的人数比较多一点,但我就是不会,没有办法, 、、、
知识广度不够,刷题太少了。
————————————————————————————————————————
就是有n道题,m次提交,ICPC赛制,让你计算最终的成绩(题数+分数)
附本题代码
——————————————————————
#include
typedef long long int LL;
using namespace std;
#define abs(x) (((x)>0)?(x):-(x))
const int N = 65535+10;
int n,m,a,b,c;
char s[100];
map<int ,int >mt,ma;
int main(){
int _;
scanf("%d",&_);
while(_--){mt.clear(),ma.clear();
scanf("%d%d",&n,&m);
int totac=0,tottime=0;
for(int i=1;i<=m;i++){
scanf("%d %d:%d %s",&a,&b,&c,s);
mt[a]+=20;
if(s[0]=='A'){
if(ma[a]==0){
totac++;
tottime+=mt[a]-20+b*60+c;
}
ma[a]=1;
}
}
printf("%d %d\n",totac,tottime);
}
return 0;
}
————————————————————————————————————————
在直线上是有n(<=3k)的屋子,每个屋子可以花费 Ci 建一个商店,或者去左边最近的去买花费是距离的差, 问你现在n个屋子的最小花费。
看到n的范围很明显的 O(n2) 左右的解法,
然后想到在按照x升序排列后 dp
设dp[i][0/1] 表示第i个屋子建商店不建商店的最小花费
转移就是
附本题代码
——————————————————————
#include
typedef long long int LL;
using namespace std;
#define abs(x) (((x)>0)?(x):-(x))
const int N = 3000+10;
const int MOD = 1e9+7;
int n,m,k;
struct node {
LL x,c;
}a[N];
LL dp[N][2];
bool cmp(node A,node B){
return A.xx;
}
LL sum[N];
int main(){
while(~scanf("%d",&n)){
for(int i=1;i<=n;i++) scanf("%lld%lld",&a[i].x,&a[i].c);
sort(a+1,a+n+1,cmp);
sum[0]=0;
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i].x;
dp[1][1] = a[1].c;
dp[2][1] = a[1].c+a[2].c;
dp[2][0] = a[1].c+a[2].x-a[1].x;
for(int i=3;i<=n;i++){
dp[i][1]=a[i].c+min(dp[i-1][1],dp[i-1][0]);
dp[i][0]=dp[1][1]+(sum[i]-sum[1]-a[1].x*(i-1));
for(int j=2;j0]=min(dp[i][0],dp[j][1]+(sum[i]-sum[j]-a[j].x*(i-j)));
}
}
// for(int i=1;i<=n;i++) printf("%lld ",sum[i]); puts("");
// for(int i=1;i<=n;i++) printf("%lld ",dp[i][1]); puts("");
// for(int i=1;i<=n;i++) printf("%lld ",dp[i][0]); puts("");
printf("%lld\n",min(dp[n][1],dp[n][0]));
}
return 0;
}
————————————————————————————————————————
给你一个序列,任选一个元素去掉,使得剩下的元素gcd值最大,问你gcd的最大值是多少
因为要去掉一个,很容易想到预处理前缀gcd和后缀gcd,然后O(n)枚举去掉的元素即可,同事维护结果的最大值
附本题代码
——————————————————————
#include
typedef long long int LL;
using namespace std;
#define abs(x) (((x)>0)?(x):-(x))
const int N = 100000+10;
const int MOD = 1e9+7;
int n,m,k;
int a[N],pre[N],suf[N];
int main(){
int _;
scanf("%d",&_);
while(_--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
pre[1]=a[1],suf[n]=a[n];
for(int i=2;i<=n;i++){
pre[i]=__gcd(pre[i-1],a[i]);
}
for(int i=n-1;i;i--){
suf[i]=__gcd(suf[i+1],a[i]);
}
// for(int i=1;i<=n;i++) printf("%d ",pre[i]);puts("");
// for(int i=1;i<=n;i++) printf("%d ",suf[i]);puts("");
int mx = max(suf[2],pre[n-1]);
for(int i=2;i1],pre[i-1]));
}
printf("%d\n",mx);
}
return 0;
}
————————————————————————————————————————
打给就是给你一个完全图,然后问你满足每个点到0节点的距离都是原图上的最小距离的生成树的个数
不会、、
————————Update—————————–
首先处理出来 两点间最短路,用floyd即可
然后考虑枚举每一条边,如果这条边
#include
typedef long long int LL;
using namespace std;
const int N = 2e5+7;
const int MOD = 1e9+7;
/****************************************************/
int n;
char a[55][55];
int b[55][55];
int dis[55][55];
LL ans[55];
int main(){
while(~scanf("%d",&n)){
memset(ans,0,sizeof(ans));
for(int i=1;i<=n;i++)scanf("%s",a[i]+1);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
b[i][j]=dis[i][j]=a[i][j]-'0';
if(b[i][j]==0) b[i][j]=dis[i][j]=1000000000;
}
b[i][i]=dis[i][i]=0;
}
// for(int i=1;i<=n;i++){
// for(int j=1;j<=n;j++)
// printf("%d ",dis[i][j]);
// puts("");
// }
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(dis[i][j]>dis[i][k]+dis[k][j])
dis[i][j]=dis[i][k]+dis[k][j];
// for(int i=1;i<=n;i++){
// for(int j=1;j<=n;j++)
// printf("%d ",dis[i][j]);
// puts("");
// }
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j&&dis[1][i]+b[i][j]==dis[1][j])
ans[j]++;
LL res = 1;
for(int j=1;j<=n;j++)
if(ans[j]>0) res=res*ans[j]%MOD;
printf("%I64d\n",res);
}
return 0;
}
————————————————————————————————————————
让你计算
因位数据范围较小,只要快速幂计算 ik 就好了,如果数据特别大的话 需要矩阵乘法做
附本题代码
——————————————————————
#include
typedef long long int LL;
using namespace std;
#define abs(x) (((x)>0)?(x):-(x))
const int N = 65535+10;
const int MOD = 1e9+7;
int n,m,k;
LL qmod(LL a,LL b){
LL res = 1ll;
while(b){
if(b&1) res=res*a%MOD;
b>>=1,a=a*a%MOD;
}
return res;
}
int main(){
int _;
while(~scanf("%d",&m)){
for(int i=1;i<=m;i++){
scanf("%d%d",&n,&k);
LL ans = 0;
for(int j=1;j<=n;j++){
ans+=qmod(j,k);
if(ans>MOD) ans-=MOD;
}
printf("%lld\n",ans);
}
}
return 0;
}
#F HDU 6028 Forgiveness
————————————————————————————————————————
没读题,不会,没人出啊.
————————————————————————————————————————
按照规则有一个图,然你在这个图上找一个完美匹配
规则如下:
1 将这个点u和标号小于u的点连一个边,
2 没有操作.
其实很简单,我们只要顺序遍历下来,如果是1的时候,前面有一个节点没有匹配,那就和当前点匹配上,
最后所有节点都匹配上yes否则no
附本题代码
——————————————————————
#include
typedef long long int LL;
using namespace std;
#define abs(x) (((x)>0)?(x):-(x))
const int N = 3000+10;
const int MOD = 1e9+7;
int n,m,k;
int main(){
int _;
scanf("%d",&_);
while(_--){
scanf("%d",&n);
int flag = 0,x;
int sum = 1;
for(int i=2;i<=n;i++){
scanf("%d",&x);
sum++;
if(x==1&&sum>=2) sum-=2;
}
if(sum==0) puts("Yes");
else puts("No");
}
return 0;
}
————————————————————————————————————————
现在有n这么长的手链,你有红色的,蓝色的石子,保证在连续奇数的区间内红色石子数不小于蓝色石子数,问方案数
首先对于保证在连续奇数的区间内红色石子数不小于蓝色石子数,
,很容易发现只要满足不存在
‘蓝蓝’,’蓝红蓝’,这两种子串就好了,
然后应该就能构造了,但是我这智商够早不出来啊,,
于是贯彻遇事不决先打表
的宗旨,
x | 2 | 3 | 4 | 5 | 6 | … | n |
---|---|---|---|---|---|---|---|
ans(x) | 3 | 4 | 6 | 9 | 13 | … | ans(i-1)+ans(i-3) |
然后构造矩阵就好了
附本题代码
————————————
#include
typedef long long int LL;
using namespace std;
#define abs(x) (((x)>0)?(x):-(x))
const int N = 3000+10;
const int MOD = 1e9+7;
int n,m,k;
const int M = 3;
struct Matrix {
LL m[M][M];
void clear0(){
for(int i=0;ifor(int j=0;j0;
}
void clear1(){
for(int i=0;ifor(int j=0;jvoid display(){
for(int i=0;ifor(int j=0;jprintf("%lld ",m[i][j]);
puts("");
}
puts("------");
}
};
Matrix operator * (Matrix &a, Matrix &b){
Matrix c;c.clear0();
for(int k=0;kfor(int i=0;ifor(int j=0;jreturn c;
}
Matrix operator ^(Matrix &a,LL b){
Matrix c;c.clear1();
while(b){
if(b&1) c=c*a;
b>>=1,a=a*a;
}
return c;
}
Matrix a,b;
void solve(LL x){
a.clear0();b.clear0();
a.m[0][0]=6,a.m[0][1]=4,a.m[0][2]=3;
b.m[0][0]=1,b.m[0][1]=1,b.m[0][2]=0;
b.m[1][0]=0,b.m[1][1]=0,b.m[1][2]=1;
b.m[2][0]=1,b.m[2][1]=0,b.m[2][2]=0;
// b.display();
b=b^(x-2);
// b.display();
a=a*b;
// a.display();
printf("%lld\n",a.m[0][2]);
}
int main(){
int _;LL x;
scanf("%d",&_);
while(_--){
scanf("%lld",&x);
solve(x);
}
return 0;
}
————————————————————————————————————————
这题是有一棵节点个数为n树,有m次查询,
查询是有两个集合,在集合中分别选出一个元素,求其LCA,问LCA的深度最大是多少
解题思路:
注意数据范围 ∑k=100000 ,那么就从这里着手么,
显然分别枚举一定不行,所以可以枚举一个集合,对另一个集合,我们可以先进行处理
大概就是进行一个dfs序,然后出现的节点我们就标记一下,这样我就能知道,当前集合的每个节点的子树有没有另一个集合的节点了,
找的时候我们将一个节点不断向上找其父节点,如果这个父节点的子树有另一个集合的元素,那么LCA就是这个父节点
然后注意几个剪枝就好了,
1,采取启发式搜索的思路,将集合内元素及其祖宗节点个数多的标记上去,对另一个小的查找
2,深度小于当前维护的最大值得父节点直接退出就好了,
3,可以先维护下这两个集合内相同元素的深度的最大值,
附本题代码
——————————————————————————————————
#include
typedef long long int LL;
using namespace std;
#define abs(x) (((x)>0)?(x):-(x))
const int N = 100000+10;
const int MOD = 1e9+7;
int read(){
int x=0;char ch = getchar();
while(ch<'0'||ch>'9') ch = getchar();
while('0'<=ch&&ch<='9') {x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x;
}
/************************************************************/
int n,m,k;
int sum[N];
#define lowbit(x) (x&-x)
void update(int i,int v){for(;i<=n;i+=lowbit(i))sum[i]+=v;}
int getSum(int i){int ans=0;for(;i;i-=lowbit(i))ans+=sum[i];return ans;}
vector<int >G[N];
int L[N],R[N],fa[N],dep[N],cnt,a[N],b[N],mx,h[N];
void dfs(int u,int f,int d){
dep[u]=d,fa[u]=f;L[u]=++cnt;
int gz=G[u].size();
for(int to,i=0;iif(to==f) continue;
dfs(to,u,d+1);
}
R[u]=cnt;
}
void solve(int x){
for(int f=x;f;f=fa[f]){
if(dep[f]<=mx) return ;
if(getSum(R[f])-getSum(L[f]-1)>0)
mx = max(mx,dep[f]);
}
}
int main(){
while(~scanf("%d%d",&n,&m)){
for(int i=1,u,v;i// scanf("%d%d",&u,&v);
u=read(),v=read();
G[u].push_back(v);
G[v].push_back(u);
}
cnt=0,dfs(1,0,1);
int x;LL ta,tb;
for(int i=1;i<=m;i++){
mx=0;ta=tb=0;
a[0]=read();
for(int j=1;j<=a[0];j++){
a[j]=read();ta+=dep[a[j]];
h[a[j]]=1;
}
b[0]=read();
for(int j=1;j<=b[0];j++){
b[j]=read();tb+=dep[b[j]];
if(h[b[j]]) mx=max(mx,dep[b[j]]);
}
if(tbfor(int j=1;j<=a[0];j++) update(L[a[j]],1);
for(int j=1;j<=b[0];j++)
if(dep[b[j]]>mx) solve(b[j]);
for(int j=1;j<=a[0];j++) update(L[a[j]],-1);
}
else {
for(int j=1;j<=b[0];j++) update(L[b[j]],1);
for(int j=1;j<=a[0];j++)
if(dep[a[j]]>mx) solve(a[j]);
for(int j=1;j<=b[0];j++) update(L[b[j]],-1);
}
printf("%d\n",mx);
for(int j=1;j<=a[0];j++) h[a[j]]=0;
}
for(int i=1;i<=n;i++) G[i].clear();
}
return 0;
}
————————————————————————————————————————————————————