条件反射,看到函数求极值果断先往三分上想,没错,这题就是个三分。
/****************************************************
* author:crazy_石头
* Pro:
* algorithm:三分
* Time:32ms
* Judge Status:Accepted
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
#define rep(i,h,n) for(int i=(h);i<=(n);i++)
#define ms(a,b) memset((a),(b),sizeof(a))
#define eps 1e-8
#define INF 1<<29
#define LL __int64
const int maxn=200000+5;
double A,B;
inline double solve(double l,double r)
{
double mid;
while(r - l >= eps)
{
mid = (l+r)/2;
double midmid = (mid+r)/2;
double tmp1 = mid * (A - B*mid)*pow(B,mid);
double tmp2 = midmid * (A - B * midmid)*pow(B ,midmid);
if(tmp1 > tmp2)
r = midmid;
else l = mid;
}
return mid * (A - mid*B)*pow(B,mid);
}
int main()
{
while(cin>>A>>B)
{
printf("%.3lf\n",solve(0,A/B));
}
return 0;
}
B题:
HDU1452 好像是。。积性函数。
贴一下别人的精简代码。。http://www.cnblogs.com/dyllove98/p/3192154.html
#include<cstdio>
#include<cstdlib>
using namespace std;
typedef __int64 ll;
ll powmol(ll x,ll y)//高次幂取模的求x^ymod29
{
ll ans=1;
x=x%29;
while(y)
{
if(y&1)ans*=x%29;//y是奇数情况的处理;
x=x*x%29;
y>>=1;//
}
return ans;
}
int main()
{
ll x,a,b,c;
while(scanf("%I64d",&x),x)
{
a=(powmol(2,2*x+1)-1)%29;
b=(powmol(3,x+1)-1)*15%29;
c=(powmol(22,x+1)-1)*18%29;
printf("%I64d\n",(a*b)%29*c%29);
}
return 0;
}
好像也是原题,好无聊。。。
/****************************************************
* author:crazy_石头
* Pro:
* algorithm:
* Time:32ms
* Judge Status:Accepted
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
#define rep(i,h,n) for(int i=(h);i<=(n);i++)
#define ms(a,b) memset((a),(b),sizeof(a))
#define eps 1e-6
#define INF 1<<29
#define LL __int64
const int maxn=200+5;
const int maxm=1000000+10;
int main()
{
int a,b;
int res[maxn]
bool ok=0;
int len=0;
int i=0,j=0;
char wall[maxn][maxn];
ms(res,0);
cin>>a>>b;
rep(i,1,a)
rep(j,1,b)
cin >> wall[i][j];
rep(j,1,b)
{
rep(i,1,a)
{
if(wall[i][j]=='0')
{
if(!ok)
{
len = 1;
ok=1;
}
else
len++;
}
else
{
if (len!=0)
{
res[len]++;
ok=0;
len=0;
}
}
}
if (len!=0)
{
res[len]++;
ok=0;
len= 0;
}
}
rep(i,1,200)
if (res[i]!=0)
cout<<i<<" "<<res[i]<<endl;
return 0;
}
D题:
BFS搞定。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=250;
const int INF=0x3f3f3f3f;
struct node{
int x,y;
int door;
bool operator < (const node &a) const{
return a.door<door;
}
};
int n,m,sx,sy,maxx,maxy;
int dis[N][N],h[N][N],l[N][N];
void BFS(){
priority_queue<node> q;
while(!q.empty())
q.pop();
for(int i=0;i<=maxx;i++)
for(int j=0;j<=maxy;j++)
dis[i][j]=INF;
node cur;
cur.x=0, cur.y=0, cur.door=0;
dis[0][0]=0;
q.push(cur);
while(!q.empty()){
cur=q.top();
q.pop();
int x=cur.x, y=cur.y;
if(x==sx && y==sy)
return ;
if(y+1<=maxy && dis[x][y+1]>dis[x][y]+h[x][y+1]){ //向上走
dis[x][y+1]=dis[x][y]+h[x][y+1];
cur.x=x;
cur.y=y+1;
cur.door=dis[x][y+1];
q.push(cur);
}
if(y-1>=0 && dis[x][y-1]>dis[x][y]+h[x][y]){ //向下走
dis[x][y-1]=dis[x][y]+h[x][y];
cur.x=x;
cur.y=y-1;
cur.door=dis[x][y-1];
q.push(cur);
}
if(x-1>=0 && dis[x-1][y]>dis[x][y]+l[x][y]){ //向左走
dis[x-1][y]=dis[x][y]+l[x][y];
cur.x=x-1;
cur.y=y;
cur.door=dis[x-1][y];
q.push(cur);
}
if(x+1<=maxx && dis[x+1][y]>dis[x][y]+l[x+1][y]){ //向右走
dis[x+1][y]=dis[x][y]+l[x+1][y];
cur.x=x+1;
cur.y=y;
cur.door=dis[x+1][y];
q.push(cur);
}
}
dis[sx][sy]=-1;
}
int main(){
//freopen("input.txt","r",stdin);
int x,y,d,t;
double f1,f2;
while(~scanf("%d%d",&n,&m)){
if(n==-1 && m==-1)
break;
maxx=-1, maxy=-1;
memset(h,0,sizeof(h));
memset(l,0,sizeof(l));
while(n--){
scanf("%d%d%d%d",&x,&y,&d,&t);
if(d==0){
for(int i=0;i<t;i++)
h[x+i][y]=INF;
maxx=max(maxx,x+t);
maxy=max(maxy,y);
}else{
for(int i=0;i<t;i++)
l[x][y+i]=INF;
maxx=max(maxx,x);
maxy=max(maxy,y+t);
}
}
while(m--){
scanf("%d%d%d",&x,&y,&d);
if(d==0)
h[x][y]=1;
else
l[x][y]=1;
}
scanf("%lf%lf",&f1,&f2);
if(f1>maxx || f2>maxy){
puts("0");
continue;
}
sx=(int)f1, sy=(int)f2;
BFS();
printf("%d\n",dis[sx][sy]);
}
return 0;
}
G题:
可以看做最小生成树吧
/****************************************************
* author:crazy_石头
* Pro:
* algorithm:
* Time:420ms
* Judge Status:Accepted
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
#define rep(i,h,n) for(int i=(h);i<=(n);i++)
#define ms(a,b) memset((a),(b),sizeof(a))
#define eps 1e-6
#define INF 1<<29
#define LL long long
const int MAXN=10000000;
int n,r;
int c[MAXN];
int parent[MAXN];
bool visited[MAXN];
int next[MAXN];
int prev[MAXN];
int rank[MAXN];
int sum[MAXN];
inline int find()
{
double max=0;
int i,flg=-1;
for(i=1;i<=n;i++)
if(max<sum[i]*1.0/rank[i] && !visited[i])
{
max=sum[i]*1.0/rank[i];
flg=i;
}
return flg;
}
inline void uni(int x)
{//合并节点,并把他们按顺序排好
int i;
for(i=parent[x];prev[i]!=-1;i=prev[i]); //合并节点
rank[i]+=rank[x];
sum[i]+=sum[x];
for(i=parent[x];next[i]!=-1;i=next[i]); //排序,接到最后一个节点上
next[i]=x;
prev[x]=i;
visited[x]=true;
}
int main()
{
while(scanf("%d %d",&n,&r),n && r)
{
int i;
for(i=1;i<=n;i++)
{
scanf("%d",&c[i]);
visited[i]=false;
prev[i]=next[i]=-1;
rank[i]=1; //合并后,集合中的规模
sum[i]=c[i]; //集合的和
}
for(i=1;i<n;i++)
{ //输入n-1个节点的父子关系
int a,b;
scanf("%d %d",&a,&b);
parent[b]=a;
}
visited[r]=true;
while(true)
{
int u=find();
if(u==-1)
break;
uni(u);
}
int cnt=0,ans=0; //cnt用于记录时间
for(i=r;i!=-1;i=next[i])
ans+=(++cnt)*c[i];
printf("%d\n",ans);
}
return 0;
}
数论,现在还不太会推。从OEIS上面搜的公式。给n个结点,问能形成多少个不同的对。好像。
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define MOD 20000003
#define LL long long
using namespace std;
LL ex[40];
LL dp[1100000];
LL jc[1100000];
LL pown(LL a,LL b,LL c)
{
LL scc,ret;
if (b==0) return 1;
else if (b==1) return a%c;
if (b&1) ret=a;else ret=1;
scc=pown(a,b/2,c);
return ret*scc%c*scc%c;
}
LL cc(LL n,LL m)
{
LL x,y,z;
x=jc[n];
y=jc[m]*jc[n-m]%MOD;
z=pown(y,MOD-2,MOD);
x=(1LL)*x*z%MOD;
return x;
}
LL getnumber(LL x)
{
if (dp[x]!=-1) return dp[x];
LL num=(log(x)/log(2));
LL i=1;
LL s1=ex[num-1]-1,s2=s1;
LL t=x-ex[num]+1;
LL xx=ex[num-1];
s1=s1+min(t,xx);
if (t>xx) s2=s2+t-xx;
dp[x]=((1LL)*cc(x-1,s1)*getnumber(s1)%MOD*getnumber(s2)%MOD);
return (dp[x]);
}
int main()
{
LL i,j,k,l,n,m;
memset(dp,-1,sizeof(dp));
dp[0]=1;
dp[1]=1;
dp[2]=1;
dp[3]=2;
ex[0]=1;
for (i=1;i<=29;i++)
ex[i]=ex[i-1]*2;
jc[0]=1;
jc[1]=1;
for (i=2;i<=1000000;i++)
jc[i]=(1LL)*jc[i-1]*i%MOD;
while (scanf("%lld",&n)!=EOF)
{
printf("%lld\n",getnumber(n));
}
return 0;
}
I题:
模拟。。
模拟剪刀石头布,很水的模拟题,直叙式模拟。。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int win[105],lose[105];
inline int comp(char s1[],char s2[])
{
switch(s1[0])
{
case 'r':
switch(s2[0])
{
case 'r':
return 0;
case 'p':
return -1;
case 's':
return 1;
}
break;
case 'p':
switch(s2[0])
{
case 'r':
return 1;
case 'p':
return 0;
case 's':
return -1;
}
break;
case 's':
switch(s2[0])
{
case 'r':
return -1;
case 'p':
return 1;
case 's':
return 0;
}
}
}
int main()
{
int n,k;
bool first=true;
while(scanf("%d%d",&n,&k)!=EOF&&n)
{
memset(win,0,sizeof(win));
memset(lose,0,sizeof(lose));
if(first)
first=false;
else
printf("\n");
int all=k*n*(n-1)/2;
for(int i=0; i<all; i++)
{
int a,b,c;
char s1[10],s2[10];
scanf("%d%s%d%s",&a,s1,&b,s2);
c=comp(s1,s2);
if(c==1)
win[a]++,lose[b]++;
else if(c==-1)
win[b]++,lose[a]++;
}
for(int i=1;i<=n;i++)
{
if(win[i]+lose[i]==0)
printf("-\n");
else
printf("%.3lf\n",(double)(win[i])/(double)(win[i]+lose[i]));
}
}
return 0;
}
PS:上面有的代码从网上贴的,未能及时注明出处,请见谅。