这场比赛特点在于两个简单题太坑,严重影响了心情。。导致最后只做出两题....当然也反映出心理素质的重要性

1002:

题意:一个矩阵b[n][n]通过数组 a[n]由以下规则构成,现在已知b[n][n]问是否有对应的数组a[n]

解法:

首先都是位运算所以不同位是不会互相影响的,即可按位考虑。

又发现,只要知道a[0]就可以算出通过b[0][]算出所有的a[],这样可以假设a[0]为0或1,由b[0][]得到一个完整的数组a[],再check这个数组a是否能正确的得到其他的b[][]即可

时间复杂度约为32*2*n^2 对于n=1000是可以接受的

当然队友是用2-SAT做的 吊吊吊吊吊orz 我就没写了,这里贴上队友的代码

代码:

#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include <stdio.h>
using namespace std; const int maxn = ; struct TwoSAT
{
int n;
vector<int> G[maxn * ];
bool mark[maxn * ];
int S[maxn * ], c; bool dfs(int x)
{
if(mark[x ^ ]) return false;
if(mark[x]) return true;
mark[x] = true;
S[c++] = x;
for(int i = ; i < G[x].size(); i++)
if(!dfs(G[x][i])) return false;
return true;
} void init(int n) // 一定要注意初始化的点数,别弄错
{
this->n = n;
for(int i = ; i < n * ; i++) G[i].clear();
memset(mark, , sizeof(mark));
} // x = xval or y = yval
void add_clause(int x, int xval, int y, int yval) // 编号从0~n-1
{
x = x * + xval;
y = y * + yval;
G[x ^ ].push_back(y);
G[y ^ ].push_back(x);
} // 当x==xval 时可推导出 y==yval
void add_edge(int x, int xval, int y, int yval)
{
x = x * + xval;
y = y * + yval;
G[x].push_back(y);
} bool solve()
{
for(int i = ; i < n * ; i += )
if(!mark[i] && !mark[i + ])
{
c = ;
if(!dfs(i))
{
while(c > ) mark[S[--c]] = false;
if(!dfs(i + )) return false;
}
}
return true;
}
}; TwoSAT solver;
int n;
int a[maxn][maxn]; bool check(int l)
{
solver.init(n);
for(int i = ; i < n; i++)
for(int j = ; j < n; j++)
{
int bit = (a[i][j] & ( << l))>>l; if(i == j)
{
if(a[i][j] != )
{
return false;
}
}
else if(a[i][j] != a[j][i])
{
return false;
}
else if(i % == && j % == ) // &
{
solver.add_edge(i, , j, bit);
solver.add_edge(j, , i, bit);
if(bit)
{
solver.add_edge(i, , i, );
solver.add_edge(j, , j, );
}
}
else if(i % == && j % == ) // |
{
solver.add_edge(i, , j, bit);
solver.add_edge(j, , i, bit);
if(!bit)
{
solver.add_edge(i, , i, );
solver.add_edge(j, , j, );
}
}
else // ^
{
solver.add_edge(i, , j, bit ^ );
solver.add_edge(j, , i, bit ^ );
solver.add_edge(i, , j, bit);
solver.add_edge(j, , i, bit);
}
}
return solver.solve();
} int main()
{ while(~scanf("%d", &n))
{
for(int i = ; i < n; i++)
for(int j = ; j < n; j++)
{
scanf("%d", &a[i][j]);
}
bool flag = true;
// 枚举每一位,l为座椅的 位数
for(int l = ; l <= ; l++)
{
if(!check(l))
{
flag = false;
break;
}
}
puts(flag?"YES":"NO");
} return ;
}

1003:

题意:

这个简单题题意挺恶心的。。先开始一直没读懂。。

小明要在五座山上采五堆蘑菇,每堆的个数是0~2012,采完后必须送出三堆和为1024倍数的蘑菇(否则全送出),回家之前如果总数大于1024还要一直被抢1024。

现在已经采了n堆(n<=5),剩下的可以任意采(0~2012)问最终最多能拿回家多少蘑菇.

解法:

分情况特判.....以下省略好多字

代码:

#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const double eps = 1e-;
int a[];
const int mod = ;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n;
while (~scanf ("%d", &n))
{
memset(a, , sizeof(a));
int sum = ;
for (int i = ; i < n; i++)
{
scanf ("%d", a+i);
sum += a[i];
}
int ans = , res = ;
if (n<=)
{
printf("%d\n", );
continue;
}
if (n == )
{
int ans = ;
bool flag = ;
for (int i = ; i < ; i++)
{
for (int j = i+; j < ; j++)
{
int tmp = a[i]+a[j];
if (tmp)
ans = max(ans, (tmp%) ? (tmp%) : );
for (int k = j +; k < ; k++)
{
if ((a[i] + a[j] + a[k]) % == )
flag = ;
}
}
}
if (flag)
printf("%d\n" , );
else
printf("%d\n" ,ans);
continue;
}
if (n == )
{
bool f = ;
int ans = ;
for (int i = ; i < ; i++)
{
for (int j = i+; j < ; j++)
{
for (int k = j+; k < ; k++)
{
int tmp = a[i] +a[j] +a[k];
if (tmp % == )
{
if (sum-tmp)
ans = max(ans, ((sum-tmp)%) ? (sum-tmp)% : );
}
}
}
}
printf("%d\n",(ans > ) ? (ans %) : ans);
}
}
return ;
}

1004:

题意:

 求y的取值范围

思路:

高中数学题,移项得到一个二次函数,然后各种分类讨论,太麻烦了没敢写。。。

1005:

题意:

一颗给定的无根树里面有边权,要求选定一个根使得此根到所有节点的代价最大,代价定义为路径上边权的最小值

解法:

奇怪的贪心,先按边权大到小排序,然后加边,并查集维护,每次合并的时候贪心的取代价最小(还是不知道为什么是对的)

代码:

 #include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const double eps = 1e-;
const int maxn = 2e5+;
int pa[maxn],rnk[maxn];
struct Edge
{
int frm, to, cst;
bool operator < (const Edge &rhs)const
{
return cst > rhs.cst;
}
}e[maxn];
int find (int x)
{
return pa[x] = (pa[x] == x ? x : find(pa[x]));
}
ll ans[maxn];
void Merge(int x, int y, int cost)
{
int fx = find(x);
int fy = find(y);
if (rnk[fx] < rnk[fy])
swap(fx, fy);
ans[fx] = max(ans[fy]+(ll)rnk[fx]*cost, ans[fx]+(ll)rnk[fy]*cost);
pa[fy] = fx;
rnk[fx] += rnk[fy];
}
void init ()
{
memset(ans, , sizeof(ans));
for (int i = ; i < maxn; i++)
{
pa[i] = i;
rnk[i] = ;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n;
while (~scanf ("%d", &n))
{
int u, v, c;
init();
for (int i = ; i < n-; i++)
{
scanf ("%d%d%d", &u, &v, &c);
e[i].frm = u, e[i].to = v, e[i].cst = c;
}
sort (e,e+n-);
for (int i = ; i < n-; i++)
{
Merge(e[i].frm, e[i].to, e[i].cst);
}
printf("%I64d\n", ans[find()]);
}
return ;
}

1008:

题意:

知道n个数的和sum,以及n个数的LCM,求合法的组成方案(排列)

解法:
发现lcm的转移只可能通过lcm的约数,(一开始和分解质因数搞呢,后来经过学长提醒发现直接找出约数即可 orz),约数数量不是很多。。这样就可以dp了

把约数哈希一下 dp[i][j][k]代表考虑到第i个数,当前lcm为总LCM的第j个约数,当前sum为k的方案数,转移很容易

代码:

#include <iostream>
#include <stdio.h>
#include<string.h>
#include<algorithm>
#include<string>
#include<ctype.h>
using namespace std;
#define MAXN 10000
const int mod=1e9+;
bool is(int p)
{
for(int i=; i*i<=p; i++)
{
if(p%i==)
return ;
}
return ;
}
int gcd(int a,int b)
{
return b==?a:gcd(b,a%b);
}
int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}
int prime[];
int s[];
int dp[][][];
int a[];
int ha[];
int l[][];
int sum,L,n,m;
int main()
{
// freopen("in.txt","r",stdin);
m=;
for(int i=; i<=; i++)
{
if(is(i))
{
prime[m++]=i;
}
}
while(scanf("%d%d%d",&sum,&L,&n)!=EOF)
{
memset(ha,-,sizeof(ha));
int lim=;
for(int i=;i<=L;i++)
{
if(L%i==)
{
ha[L/i]=lim;
s[lim++]=L/i;
}
}
for(int i=;i<lim;i++)
{
for(int j=;j<lim;j++)
{
l[i][j]=lcm(s[i],s[j]);
}
}
memset(dp,,sizeof(dp));
dp[][][lim-]=;
for(int i=;i<=n;i++)
{
for(int j=;j<=sum;j++)
{
for(int k=;k<lim;k++)
{
if(!dp[i-][j][k])
continue;
for(int t=;t<lim;t++)
{
if(j+s[t]<=sum)
{
if(ha[l[k][t]]==-)
continue;
dp[i][j+s[t]][ha[l[k][t]]]+=dp[i-][j][k];
dp[i][j+s[t]][ha[l[k][t]]]%=mod;
}
}
}
}
}
cout<<dp[n][sum][]<<endl;
}
return ;
}

1010:

题意:
一个大矩形被一些线段分成了小矩形,现在给定两个点的坐标,求出删除一些线段使这两点在同一矩形后剩余矩形数量的最大值。

思路:

其实就是要找所求两点共同所在的最小的矩形(除此之外的线段都不删除,得到的剩余矩形数肯定最多)。

而按照题意的分割矩形法其实就是形成了一颗树,这样就发现两个点所在的最小矩形其实是这两个点当前所在矩形的lca

理论ac了。。代码还没写

1011:

题意:

给定一个等比数列 1(或者0)+k+k^2+....k^r的和 S,要求求出r 和k,多解首先满足r*k最小,然后满足 r最小

解法:

由于k>=2所以可以计算发现r最大为40,则可以枚举r,二分求得k ,如果r和二分出的k刚好等于 k或者k-1 则符合题意,可以统计答案

坑点是二分过程中容易溢出

代码:

#include <iostream>
#include <stdio.h>
using namespace std;
typedef long long ll; ll n; ll equ(ll ak , int r)
{
ll ans = ;
ll k = ak;
for(int i = ; i <= r; i++)
{
ans += k;
if(ans > n + )
break;
if(ans<=)
return 10000000000000LL;
k *= ak;
}
return ans;
} int main()
{ while(~scanf("%I64d", &n))
{
ll ansk = 10000000000000LL;
int ansr = ; // 枚举r
for(int r = ; r <= ; r++)
{
// 二分k
ll l = , R = 1000000000001LL;
while(l < R)
{
ll m = (l + R + ) / ;
if(equ(m, r) <= n)
{
l = m;
}
else
{
R = m - ;
}
} ll k = l;
if(equ(k, r) == n)
{
// 保存答案
if((ansk * ansr > k * r) || ((ansk * ansr == k * r) && ansr > r))
{
ansk = k;
ansr = r;
}
} // 二分k
l = , R = 1000000000001LL;
while(l < R)
{
ll m = (l + R + ) / ;
if(equ(m, r) <= n + )
{
l = m;
}
else
{
R = m - ;
}
} k = l;
if(equ(l, r) == n + )
{
// 保存答案
if((ansk * ansr > k * r) || ((ansk * ansr == k * r) && ansr > r))
{
ansk = k;
ansr = r;
}
}
}
printf("%d %I64d\n", ansr, ansk);
} return ;
}

【2012长春区域赛】部分题解 hdu4420—4430的更多相关文章

  1. 2015年ACM长春区域赛比赛感悟

    距离长春区域赛结束已经4天了,是时候整理一下这次比赛的点点滴滴了. 也是在比赛前一周才得到通知要我参加长春区域赛,当时也是既兴奋又感到有很大的压力,毕竟我的第一场比赛就是区域赛水平,还是很有挑战性的. ...

  2. 【2012天津区域赛】部分题解 hdu4431—4441

    1001: 题意:给你13张麻将牌,问可以胡哪些张 思路: 枚举可能接到的牌,然后dfs判断能否胡 1002: 题意: 已知n,m 求 n的所有约数在m进制下的平方和 做法:队长用java高精度写的 ...

  3. HDU 5527 Too Rich ( 15长春区域赛 A 、可贪心的凑硬币问题 )

    题目链接 题意 : 给出一些固定面值的硬币的数量.再给你一个总金额.问你最多能用多少硬币来刚好凑够这个金额.硬币数量和总金额都很大   分析 : 长春赛区的金牌题目 一开始认为除了做类似背包DP那样子 ...

  4. HDU 4818 RP problem (高斯消元, 2013年长春区域赛F题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4818 深深地补一个坑~~~ 现场赛坑在这题了,TAT.... 今天把代码改了下,过掉了,TAT 很明显 ...

  5. 2018-2019 ACM-ICPC 徐州区域赛 部分题解

    题目链接:2018-2019 ACM-ICPC, Asia Xuzhou Regional Contest A. Rikka with Minimum Spanning Trees 题意: 给出一个随 ...

  6. Travel(HDU 5441 2015长春区域赛 带权并查集)

    Travel Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Su ...

  7. hdu 4463 有一条边必须加上 (2012杭州区域赛K题)

    耐克店 和 苹果店必须相连 Sample Input42 30 01 00 -1 1 -10 Sample Output3.41 # include <iostream> # includ ...

  8. ACM学习历程——HDU4472 Count(数学递推) (12年长春区域赛)

    Description Prof. Tigris is the head of an archaeological team who is currently in charge of an exca ...

  9. ICPC2019上海区域赛 部分题解(正在更新)

    K. Color Graph 题意: 给定一个简单图,点个数<=16,删去部分边后,使得该图中无边数为奇数得环,问剩下的边数最大为多少? 思路: 如果一个图中无奇数边的环,那么这个图一定是个二分 ...

随机推荐

  1. POJ 1458-Common Subsequence(线性dp/LCS)

    Common Subsequence Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 39009   Accepted: 15 ...

  2. Example of how to use both JDK 7 and JDK 8 in one build.--reference

    JDK 8 Released Most of us won’t be able to use/deploy JDK 8 in production for a looong time. But tha ...

  3. 【酷Q插件制作】教大家做一个简单的签到插件

    酷Q插件已经有很多了,社区分享一大堆,不过还是自己写才有乐趣,哈哈.不得不吐槽一下,酷Q竟然不更新了,出了个酷Q pro,还收费!!诶.不过这也影响不了咱写插件的心情,今天教大家写一个酷Q签到插件,虽 ...

  4. android使用微软EWS发送邮件

    通常我们在android使用javamail发送邮件,可是很多时候我们需要连接Exchange服务(很多公司内部邮件服务器采用,并且未开通smtp服务)来发送邮件,这时候我们就要用到微软的 ews-j ...

  5. sql 常用语法汇总

    Sql常用语法 SQL分类: DDL—数据定义语言(CREATE,ALTER,DROP,DECLARE) DML—数据操纵语言(SELECT,DELETE,UPDATE,INSERT) DCL—数据控 ...

  6. 【网络流#7】POJ 3281 Dining 最大流 - 《挑战程序设计竞赛》例题

    不使用二分图匹配,使用最大流即可,设源点S与汇点T,S->食物->牛->牛->饮料->T,每条边流量为1,因为流过牛的最大流量是1,所以将牛拆成两个点. 前向星,Dini ...

  7. python的行与缩进

    #coding=utf-8#逻辑行与物理行#以下是3个物理行print "abc"print "789"print "777" #以下是1个 ...

  8. 安装Linux和Windows的双系统

    平时使用较多的操作系统是Windows,想玩玩Linux平时也是在虚拟机上,强迫症的怎么能忍,一直想装个双系统,也能强迫自己练习Linux命令,之前重装系统的时候也试着装了一下,但是准备不够充分.结果 ...

  9. String[]和ArrayList和LinkedList区别

    String[]和ArrayList和LinkedList区别 参考文档如下: http://www.blogjava.net/flysky19/articles/92775.html http:// ...

  10. Windows下查看端口被程序占用的方法

      有时安装程序时,会出现XX端口被占用的情况,可以通过CMD命令查看什么程序占用 1. netstat -ano 查看相应端口对应程序的PID 例如:   C:\>netstat -ano A ...