A - BBP Formula HDU - 6217
题意:给了 π 的BBP近似公式,求出来的是10进制值,问如果用16进制表示 π 的小数点后第n位是啥
分析:典型的BBP问题tl
我们可以从这个公式中得出,可以先乘 16n−1 ,小数部分求出来,然后小数部分再乘16,这个整数部分就是我们的答案。
为什么不直接乘 16n ,然后答案就是整数部分mod16…emmm,这个给你们根据式子想想~
#include
using namespace std;
typedef long long ll;
int n;
ll qm(ll a,int n,int mod)
{
ll ans = 1 ;
while(n)
{
if(n&1) ans = ans*a%mod;
a = a*a%mod;
n>>=1;
}
return ans%mod;
}
double BBP(int n,int t)
{
double ans = 0;
for(int i=0;i<=n;i++)
ans +=(double)qm(16,n-i,t+8*i)/(t+8*i);
for(int i=n+1;i<=n+1000;i++)
ans +=pow(16,n-i)/(8*i+t);
return ans;
}
int main()
{
int T,case1=1;;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
n--;
double ans = 4*BBP(n,1)-2*BBP(n,4)-BBP(n,5)-BBP(n,6);
//cout<//cout<<(int)ans<int)ans;
if(ans<0) ans+=1;
ans = ans*16;
int t =(int)ans;
// cout<printf("Case #%d: %d ",case1++,n+1);
if(t>=0&&t<=9) printf("%c\n",t+'0');
else printf("%c\n",t-10+'A');
}
return 0;
}
F - Heron and His Triangle HDU - 6222
题意:三个连续的整数t-1,t,t+1,组成三角形,并且三角形的面积是整数。问不小于n的t值是多少
分析:因为这个t是不会大的。直接用java,打表找规律~
(我开始还化简了好久,,然后再打的..真应该直接无脑打个先看看..
import java.math.BigInteger;
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
BigInteger[] a = new BigInteger[105];
BigInteger x = new BigInteger("4");
BigInteger y = new BigInteger("14");
a[0] = x;a[1]= y;
int id = 2;
BigInteger lim = BigInteger.TEN.pow(30);
while(y.compareTo(lim)<=0)
{
BigInteger k = new BigInteger("4");
BigInteger t = k.multiply(y).subtract(x);
x = y;
y = t;
a[id++] = y;
}
Scanner in = new Scanner(System.in);
int t;
t = in.nextInt();
BigInteger n;
while(t-->0)
{
n = in.nextBigInteger();
int i=0;
y = a[i];
while(y.compareTo(n)<0)
{
i++;
y = a[i];
}
System.out.println(a[i]);
}
}
}
G - Infinite Fraction Path HDU - 6223
题意:给一个串,长度为n,由0-9,10个数字组成。有一个转移规律,下标为i下一步会转移到(i*i+1)%n的位置上。问从一个点开始,走转移n-1步,走过的路径(为经过位置的值)字典序最大的是啥
分析:….
直接将最大值入队,
然后对于每一层,如果这一步走的值不是最大的,那么就删去
如果这一层中有下标相同的也可以删去
(这个思想过了,但是wo还是不能证明为什么这个暴力不会超时..
(队友说还有后缀数组的方法,下次问他之后再加上~
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
const int maxn = 150100;
char str[maxn];
int s[maxn],ans[maxn],vis[maxn];
ll zy[maxn];
struct node{
ll id;int step,z;
};
struct compare
{
bool operator()(const node &a,const node &b) const //ans最小值优先 权值最大值优先
{
if(a.step!=b.step) return a.step>b.step;
else if(a.z!=b.z) return a.zreturn a.id>b.id;
}
};
priority_queuevector,compare > q;
int main()
{
int T,case1=1;
scanf("%d",&T);
while(T--)
{
while(!q.empty()) q.pop();
int n,maxx=0;
scanf("%d",&n);
scanf("%s",str);
mem(ans,-1);mem(vis,-1);mem(s,0);
for(int i=0;i'0';maxx=max(maxx,s[i]);zy[i]=((ll)i*(ll)i+1ll)%(ll)n;}
for(int i=0;iif(s[i]==maxx) {node a;a.id=i;a.z=s[i];a.step=0;q.push(a);}
while(!q.empty())
{
node t = q.top();q.pop();
if(t.step==n) continue;
if(ans[t.step]==-1) ans[t.step] = t.z;
else if(ans[t.step]<=t.z) ans[t.step]=t.z;
else continue;
if(vis[t.id]else continue;
ll tmp = zy[t.id];
node a1;a1.id = tmp;a1.z=s[tmp];a1.step=t.step+1;
q.push(a1);
}
//printf("Case #%d: ",kase++);
printf("Case #%d: ",case1++);
for(int i=0;iprintf("%d",ans[i]);
printf("\n");
}
return 0;
}
I - Little Boxes HDU - 6225
题意:给四个数,问四个数加起来的值
分析:用java真是方便。因为数据范围有点大,然后用longlong会爆掉,然后用double卡下精度也失败了。然后就只能大数了~
L - Tree HDU - 6228
题意:给一棵树,给k种不同颜色去涂这树上的节点,Ei表示用第i种颜色涂的节点连起来的最小边集。问E1 ∩ E2 ∩ E3 ∩ … ∩ Ek的最大值
分析:就是统计哪些点的(孩子个数+1)和(父亲个数+1)(除去孩子个数)>=(k),然后答案就是这些点的数量。+1表示加上自己~
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 200010;
struct node{
int to,pre;
}e[maxn*2];
int head[maxn],h=0,vis[maxn],num[maxn];
void init()
{
mem(vis,0);mem(head,-1);mem(num,0);h=0;
}
int addedge(int from,int to)
{
e[h].to=to;e[h].pre = head[from];head[from]=h;h++;
}
void dfs(int u)
{
vis[u]=1;num[u]=1;
for(int i=head[u];i>-1;i=e[i].pre)
{
int v = e[i].to;
if(vis[v]) continue;
dfs(v);
num[u]+=num[v];
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
int n,k;
scanf("%d %d",&n,&k);
for(int i=0;i1;i++)
{
int x,y;
scanf("%d %d",&x,&y);
addedge(x,y);addedge(y,x);
}
dfs(1);
int ans=0;
for(int i=1;i<=n;i++)
{
if(num[i]>=k&&(n-num[i])>=k) ans++;
}
printf("%d\n",ans);
}
}
M - Wandering Robots HDU - 6229
题意:在一个n*n网格中,有一个机器人,然后每个单位时间,它可能有5种操作,向上,下,左,右走,不动。有k个障碍物在网格中,当然它不能走出网格,以及走到障碍物的格子中。问它可能在x+y>=(n-1)的概率是多少。
(x,y)为坐标,x,y ∈ [0,n-1]
题解:找规律?
来看第一个样例
n=3,k=0;
每个格子的可能性为
3 4 3
4 5 4
3 4 3
ans=(33-11)/33;
第二个样例
n=3,k=1;
障碍物:(1,1)
每个格子的可能性为
3 3 3
3 0 3
3 3 3
ans=(24-9)/24=5/8;
然后验证一下后面的例子,发现答案…
模拟一下就行了
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 150;
int dp[maxn][maxn][maxn];
int sum[maxn];
int gcd(int a,int b)
{
if(b==0) return a;
else return gcd(b,a%b);
}
int main()
{
int T,cas = 1;
scanf("%d",&T);
while(T--)
{
int n,k;
set<int> Set;
scanf("%d %d",&n,&k);
int sum=1,a=0;
if(n<=0) {printf("Case #%d: %d/%d\n",cas++,sum-a,sum);continue;}
if(n>1){
sum = 5*n*n-2*4-4*(n-2);
a = 3+8*(n-2)+(n-2)*(n-3)/2*5;
}
for(int i=0;iint x,y;
scanf("%d %d",&x,&y);
int temp = x*n+y,b=0;
if(Set.count(temp)) continue;
else {
Set.insert(temp);
int tmp=0;
if(temp>=n) {b++;tmp=temp-n;if(Set.count(tmp)==0) {sum--;if(x-1+y<(n-1))a--;}else b--;}
if(temp1)) {b++;tmp=temp+n;if(Set.count(tmp)==0){sum--;if(x+1+y<(n-1)) a--;}else b--;}
if(temp%n>0) {b++;tmp=temp-1;if(Set.count(tmp)==0) {sum--;if(x+y-1<(n-1)) a--;}else b--;}
if(temp%n<(n-1)) {b++;tmp=temp+1;if(Set.count(tmp)==0){sum--;if(x+y+1<(n-1))a--;}else b--;}
sum-=(b+1);if(x+y<(n-1)) a-=(b+1);
}
}
int t=1;
if(sum!=0)t=gcd(sum-a,sum);
printf("Case #%d: %d/%d\n",cas++,(sum-a)/t,sum/t);
}
return 0;
}
/*
5
5 4
1 1
1 2
2 3
3 2
*/