2014湘潭赛

A题:

XTU 1203 A simple problem

第一次碰见这种卡常数的题。。。。。

刚开始用的long long发现还是不够,然后找了个大数模板

接下来就无限TLE,然后各种优化。。。。。

总结了下大数运算的几个优化要点

一、能不能大数的地方尽量少用大数

二、大数的数组开到够用就行,不要开太大

还有就是这道题的一个优化,暴力求前半部分的时候,可以把临界的数适当取大一点

/*
 * Author:        lj94093
 * Created Time:  2015/5/27 星期三 下午 5:30:26
 * File Name:     A simple problem.cpp
 */
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
#define out(x) cout<<#x<<": "<<x<<endl
const double eps(1e-8);
const int maxn=10100;
const long long inf=-1u>>1;
typedef long long ll;
ll n;
struct BigInt{
	const static int mod=10000;
	const static int DLEN=4;
	int a[8],len;
	BigInt(){
		memset(a,0,sizeof(a));
		len=1;
	}
	BigInt(ll v){
		memset(a,0,sizeof(a));
		len=0;
		do{
			a[len++]=v%mod;
			v/=mod;
		}while(v);
	}
	BigInt operator +(const BigInt &b)const{
		BigInt res;
		res.len=max(len,b.len);
		for(int i=0;i<=res.len;i++) res.a[i]=0;
		for(int i=0;i<res.len;i++) {
			res.a[i] += ((i < len)?a[i]:0)+((i < b.len)?b.a[i]:0);
			res.a[i+1] += res.a[i]/mod;
			res.a[i] %= mod;
		}
		if(res.a[res.len]>0) res.len++;
		return res;
	}

	BigInt operator *(const BigInt &b)const{
		BigInt res;
		for(int i=0;i<len;i++){
			int up=0;
			for(int j=0;j<b.len;j++){
				int tmp=a[i]*b.a[j]+res.a[i+j]+up;//i位*j位,至少有i+j位
				res.a[i+j]=tmp%mod;
				up=tmp/mod;
			}
			if(up!=0){
				res.a[i+b.len]=up;
			}
		}
		res.len=len+b.len;
		while(res.a[res.len-1]==0 && res.len>1) res.len--;//调整长度
		return res;
	}
	void output(){
		printf("%d",a[len-1]);
		for(ll i=len-2;i>=0;i--) {
			printf("%04d",a[i]);//中间的显示前导0
		}
		printf("\n");
	}
};
int t,cas=1;

void init() {
	scanf("%I64d",&n);
}

void work() {
	BigInt ans=0;
	//ll ans1=0;
	int tmp;
	ll i;
	ll m=sqrt(n*1.0);
	if(m*10<=n) m=m*10;
	ll s=0;
	for(i=1;i<=m;i++){
		s+=n%i;
		tmp=i;
	}
	ans=ans+s;
	ll k=n/(tmp+1),l,r,cnt1,cnt2;
	for(l=tmp+1;k!=0;k--,l=r+1){
		r=n/k;
		cnt1=(n%l)/k;
		cnt2=cnt1+1;
		ans=ans+BigInt((n%r)*cnt2);
		//printf("%I64d %I64d\n",n%r,cnt2);
		if(cnt1&1) cnt2>>=1;
		else cnt1>>=1;
		ans=ans+BigInt(k*cnt1)*BigInt(cnt2);
	}
	printf("Case %d: ",cas++);
	ans.output();
	/*ll ans1=0;
	for(ll i=1;i<=n;i++){
		ans1+=n%i;
	}
	printf("Case %d: %I64d\n",cas++,ans1);*/
}

int main() {
	#ifndef ONLINE_JUDGE
	//freopen("in.txt","r",stdin);
	#endif
	scanf("%d",&t);
	while(t--){
		init();
		work();
	}

	return 0;
}

XTU1205 Range

一开始觉得用线段树,写了一会发现太难写,就觉得还有其他做法

想了个用ST+二分的做法,结果超时了。。。

然后搜解题报告,说是用单调栈,据说单调栈在处理最大最小值时会很好用

结合我以前后缀数组时用过的一个单调栈来看,单调栈主要解决在连续多个数之间的大小比较

注释过了的是AC代码,没注释的是ST+二分的代码,虽然超时了,但觉得这应该也是一种思路

#include<stdio.h>
#include<string.h>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<math.h>
using namespace std;
#define out(x) cout<<#x<<": "<<x<<endl
const double eps(1e-8);
const int maxn=101000;
const long long inf=-1u>>1;
typedef long long ll;
int n,a[maxn],Max[maxn][20],Min[maxn][20];
void init_rmq(){
	for(int i=1;i<=n;i++) Min[i][0]=Max[i][0]=a[i];
	
	for(int j=1;(1<<j)<=n;j++){
		for(int i=n;i>=1;i--){
			if(i+(1<<(j-1))>n) {//上一层的一半长度都已经超过了,则这一层肯定也会超过,直接继承 
				Max[i][j]=Max[i][j-1];
				Min[i][j]=Min[i][j-1];
			}
			else{
				Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);
				Min[i][j]=min(Min[i][j-1],Min[i+(1<<(j-1))][j-1]);
			}
		}
	}
	
}
int max_ask_rmq(int l,int r){
	int j=log(r-l+1.0)/log(2.0);
	return max(Max[l][j],Max[r-(1<<j)+1][j]);
}
int min_ask_rmq(int l,int r){
	int j=log(r-l+1.0)/log(2.0);
	return min(Min[l][j],Min[r-(1<<j)+1][j]);
}
void init() {
	scanf("%d",&n);
	for(int i=1;i<=n;i++) {
		scanf("%d",&a[i]);
	}
	init_rmq();
}
int find_greater_r(int l,int r,int i){
	if(l>r) return l-1;
	if(max_ask_rmq(l,r)<a[i]) return r;
	int mid=(l+r)>>1;
	while(l+1<r){
		if(max_ask_rmq(l,mid)<a[i]) l=mid;
		else r=mid;
		mid=(l+r)>>1;
	}
	if(a[l]>=a[i]) return l-1;
	else return r-1;
}
int find_greater_l(int l,int r,int i){
	if(max_ask_rmq(l,r)<=a[i]) return l;
	int mid=(l+r)>>1;
	while(l+1<r){
		if(max_ask_rmq(mid,r)<=a[i]) r=mid;
		else l=mid;
		mid=(l+r)>>1;
	}
	return r;
}
int find_less_r(int l,int r,int i){
	if(l>r) return l-1;
	if(min_ask_rmq(l,r)>a[i]) return r;
	int mid=(l+r)>>1;
	while(l+1<r){
		if(min_ask_rmq(l,mid)>a[i]) l=mid;
		else r=mid;
		mid=(l+r)>>1;
	}
	if(a[l]<=a[i]) return l-1;
	else return r-1;
}
int find_less_l(int l,int r,int i){
	if(min_ask_rmq(l,r)>=a[i]) return l;
	int mid=(l+r)>>1;
	while(l+1<r){
		if(min_ask_rmq(mid,r)>=a[i]) r=mid;
		else l=mid;
		mid=(l+r)>>1;
	}
	return r;
}
void work() {
	ll ans=0;
	for(int i=1;i<=n;i++){
		int left,right;
		
		left=find_greater_l(1,i,i);
		right=find_greater_r(i+1,n,i);
		ans+=(ll)(right-i+1)*(i-left+1)*a[i];//该数作为最大值被计算了times次
		
		left=find_less_l(1,i,i);
		right=find_less_r(i+1,n,i);
		//printf("%d\n",i);
		ans-=(ll)(right-i+1)*(i-left+1)*a[i];
		//printf("%d\n",right);
	}
	ans+=n*(n+1)/2; 
	printf("%I64d\n",ans);
}

int main() {
	#ifndef ONLINE_JUDGE
	freopen("in.txt","r",stdin);
	#endif
	int t,cas=1;
	scanf("%d",&t);
	while(t--){
		init();
		printf("Case %d: ",cas++);
		work();
	}
	
	return 0;
}
/*
#include<stdio.h>
#include<string.h>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<math.h>
using namespace std;
#define out(x) cout<<#x<<": "<<x<<endl
const double eps(1e-8);
const int maxn=101000;
const long long inf=-1u>>1;
typedef long long ll;
int n,a[maxn],sta1[maxn],sta2[maxn],suml1[maxn],sumr1[maxn],suml2[maxn],sumr2[maxn];
void init() {
<span style="white-space:pre">	</span>scanf("%d",&n);
<span style="white-space:pre">	</span>for(int i=1;i<=n;i++) {
<span style="white-space:pre">		</span>scanf("%d",&a[i]);
<span style="white-space:pre">	</span>}
}
void work() {
<span style="white-space:pre">	</span>ll ans=0;
<span style="white-space:pre">	</span>int top1=1,top2=1,l1,l2,r1,r2;
<span style="white-space:pre">	</span>sta1[0]=sta2[0]=0;
<span style="white-space:pre">	</span>for(int i=1;i<=n;i++){//与左边的相比作为最大值 
<span style="white-space:pre">		</span>while(top1>1&&a[i]>=a[sta1[top1-1]]) top1--;
<span style="white-space:pre">		</span>l1=sta1[top1-1]+1;
<span style="white-space:pre">		</span>sta1[top1++]=i;
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>while(top2>1&&a[i]<=a[sta2[top2-1]]) top2--;
<span style="white-space:pre">		</span>l2=sta2[top2-1]+1;
<span style="white-space:pre">		</span>sta2[top2++]=i;
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>suml1[i]=i-l1+1;
<span style="white-space:pre">		</span>suml2[i]=i-l2+1;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>top1=top2=1;
<span style="white-space:pre">	</span>sta1[0]=sta2[0]=n+1;
<span style="white-space:pre">	</span>for(int i=n;i>=1;i--){
<span style="white-space:pre">		</span>while(top1>1&&a[i]>a[sta1[top1-1]]) top1--;
<span style="white-space:pre">		</span>r1=sta1[top1-1]-1;
<span style="white-space:pre">		</span>sta1[top1++]=i;
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>while(top2>1&&a[i]<a[sta2[top2-1]]) top2--;
<span style="white-space:pre">		</span>r2=sta2[top2-1]-1;
<span style="white-space:pre">		</span>sta2[top2++]=i;
<span style="white-space:pre">		</span>sumr2[i]=r2-i+1;
<span style="white-space:pre">		</span>sumr1[i]=r1-i+1;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>ans=0;
<span style="white-space:pre">	</span>for(int i=1;i<=n;i++) {
<span style="white-space:pre">		</span>ans+=(ll)suml1[i]*sumr1[i]*a[i];
<span style="white-space:pre">		</span>ans-=(ll)suml2[i]*sumr2[i]*a[i];
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>ans+=n*(n+1)/2; 
<span style="white-space:pre">	</span>printf("%I64d\n",ans);
}


int main() {
<span style="white-space:pre">	</span>#ifndef ONLINE_JUDGE
<span style="white-space:pre">	</span>//freopen("in.txt","r",stdin);
<span style="white-space:pre">	</span>#endif
<span style="white-space:pre">	</span>int t,cas=1;
<span style="white-space:pre">	</span>scanf("%d",&t);
<span style="white-space:pre">	</span>while(t--){
<span style="white-space:pre">		</span>init();
<span style="white-space:pre">		</span>printf("Case %d: ",cas++);
<span style="white-space:pre">		</span>work();
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>return 0;
}
*/
XTU1205   Dormitory's Elevator

dp,这道题不同于以前的对某个点选或不选的地方在于,第i层可能由第i-2层,i-3层,i-4层的影响

画一下图发现受i-4层影响是不可能的,因为这样的话可以在i-2层停。。。

这样题目就变得简单了

dp[i]表示前i层,停在第i层时最小消耗的能量

还有很重要的一点,这道题有问题,A和B给出的时候应该是先B后A,害我无限WA

#include<stdio.h>
#include<string.h>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<math.h>
using namespace std;
#define out(x) cout<<#x<<": "<<x<<endl
const double eps(1e-8);
const int maxn=100100;
const long long inf=-1u>>1;
typedef long long ll;
int n,m,up,down;
int a[maxn],dp[maxn];
void init() {
	int tmp;
	memset(a,0,sizeof(a));
	scanf("%d%d%d%d",&n,&m,&up,&down);
	for(int i=0;i<=n;i++) dp[i]=inf;
	for(int i=0;i<m;i++) {
		scanf("%d",&tmp);
		a[tmp]++;
	}
}
//dp[i]:前i层,电梯停在第i层花费的最小能量 
void work() {
	int mini=min(up,down);
	dp[0]=0;
	dp[1]=0;
	dp[2]=a[1]*down;
	dp[3]=mini*a[2];
	int ans=0;
	for(int i=4;i<=n;i++){
		dp[i]=min(dp[i-2]+a[i-1]*mini,dp[i-3]+min(up,down*2)*a[i-1]+min(down,up*2)*a[i-2]);
	}
	ans=min(dp[n],dp[n-1]+a[n]*up);
	printf("%d\n",ans);
}

int main() {
	#ifndef ONLINE_JUDGE
	freopen("in.txt","r",stdin);
	#endif
	int t;
	scanf("%d",&t);
	for(int cas=1;cas<=t;cas++){
		init();
		printf("Case %d: ",cas);
		work();
	}
	
	return 0;
}

XTU 1207  Welcome to XTCPC

纯粹就是打广告的题。。。-_-||

#include<stdio.h>
#include<string.h>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<math.h>
using namespace std;
#define out(x) cout<<#x<<": "<<x<<endl
const double eps(1e-8);
const int maxn=10100;
const long long inf=-1u>>1;
typedef long long ll;
char s[1000]; 
void init() {
	scanf("%s",s);
	
}

void work() {
	int len=strlen(s),cnt=0,ans=1;
	for(int i=0;i<len;i++){
		if(ans==1&&s[i]=='X') ans++;
		else if(ans==2&&s[i]=='T') ans++;
		else if(ans==3&&s[i]=='C') ans++;
		else if(ans==4&&s[i]=='P') ans++;
		else if (ans==5&&s[i]=='C') ans++;
		if(ans==6) break;
	}
	if(ans==6) printf("Yes\n");
	else printf("No\n");
}

int main() {
	#ifndef ONLINE_JUDGE
	freopen("in.txt","r",stdin);
	#endif
	int t,cas=1;
	scanf("%d",&t);
	while(t--){
		init();
		printf("Case %d: ",cas++);
		work();
	}
	
	return 0;
}

XTU1209  Alice and Bob

横的能减的次数+竖的能减的次数,对2取模

#include<stdio.h>
#include<string.h>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<math.h>
using namespace std;
#define out(x) cout<<#x<<": "<<x<<endl
const double eps(1e-8);
const int maxn=10100;
const long long inf=-1u>>1;
typedef long long ll;
int w,h;
void init() {
	scanf("%d%d",&w,&h);
}

void work() {
	int cnt1=0,cnt2=0;
	while(w){
		if((w&(1<<cnt1))==0) cnt1++;
		else break;
	}
	while(h){
		if((h&(1<<cnt2))==0) cnt2++;
		else break;
	}
	int cnt=cnt1+cnt2;
	//printf("%d\n",cnt);
	if(cnt&1) printf("Alice\n");
	else printf("Bob\n");
}

int main() {
	#ifndef ONLINE_JUDGE
	//freopen("in.txt","r",stdin);
	#endif
	int t,n,cas=1;
	scanf("%d",&t);
	while(t--){
		init();
		printf("Case %d: ",cas++);
		work();
	}
	
	return 0;
}

XTU1210 还是因为n只有10e6,直接递推就好了

#include<stdio.h>
#include<string.h>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<math.h>
using namespace std;
#define out(x) cout<<#x<<": "<<x<<endl
const double eps(1e-8);
const int maxn=10100;
const long long inf=-1u>>1;
typedef long long ll;
int n;
int a[1000005],b[10];
void init() {
	scanf("%d",&n);
}
int judge(int m) {
	int len=0,cnt=0;
	while(m){
		b[++len]=m%10;
		if(b[len]==7) cnt++;
		m/=10;
	}
	if(cnt==len||cnt==len-1) return 1;
	else return 0;
}

int main() {
	#ifndef ONLINE_JUDGE
	freopen("in.txt","r",stdin);
	#endif
	for(int i=1;i<=1000000;i++) {
		if(judge(i)) a[i]=a[i-1]+1;
		else a[i]=a[i-1];
	}
	int t,cas=1;
	scanf("%d",&t);
	
	while(t--){
		init();
		printf("Case %d: ",cas++);
		printf("%d\n",a[n]);
	}
	
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值