码迷,mamicode.com
首页 > 其他好文 > 详细

NOIP hzwer second - xgtao -

时间:2016-08-01 08:02:28      阅读:189      评论:0      收藏:0      [点我收藏+]

标签:

技术分享

技术分享

技术分享

 

 

这一道题有两种做法:

1:构建矩阵,根据斐波拉契数列数列类比,得到矩阵过后根据fi直接解出t(因为fi是小于19960515的所以过程中不会去"%",所以可以直接除以系数,不

用逆元),再用矩阵算出fj

                                                       |fn+1 |     |1 1|n   * |f1|

                                                       |fn     |       |0 1|    * |f0|

2:找规律推性质:

      f0 =        1
      f1 = 1t
      f2 = 1t + 1
      f3 = 2t + 1
      f= 3t + 2
      f= 5t + 3

 那么归纳得fn = Fn-1*t + Fn-2    Fn是斐波拉契数列第n项

 

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int mod = 19960515;

struct Matrix{
	int map[3][3];
	void init(bool flag){
		memset(map,0,sizeof(map));
		if(flag)for(int i = 0;i < 3;++i)map[i][i] = 1;
	}
}ori,pou;

Matrix mul(Matrix x,Matrix y){
	Matrix ret;ret.init(0);
	for(int i = 0;i < 3;++i){
		for(int j = 0;j < 3;++j){
			for(int k = 0;k < 3;++k){
				ret.map[i][j] = (ret.map[i][j]+(long long)x.map[i][k]*y.map[k][j])%mod;
			}
		}
	}
	return ret;
}

Matrix Pow(Matrix x,int cnt){
	Matrix ret;ret.init(1);
	while(cnt){
		if(cnt & 1)ret = mul(ret,x);
		x = mul(x,x);
		cnt>>=1;
	}
	return ret;
}

int main(){
	freopen("gibonacci.in","r",stdin);
	freopen("gibonacci.out","w",stdout);
	int T,xi,i,j,t;
	scanf("%d",&T);
	ori.map[0][0] = 1,ori.map[0][1] = 1;
	ori.map[1][0] = 1,ori.map[1][1] = 0;
	while(T--){
		scanf("%d%d%d",&i,&xi,&j);
		Matrix ret;ret.init(0);
		ret = Pow(ori,i);
		if((xi-ret.map[1][1]) % ret.map[1][0] != 0){
			printf("-1\n");
			continue;
		}
		t = (xi-ret.map[1][1]) / ret.map[1][0];
		Matrix k;k.init(0);
		k.map[0][0] = t;k.map[1][0] = 1;
		ret = Pow(ori,j);
		ret = mul(ret,k);
		printf("%d\n",ret.map[1][0]);
	}
	return 0;
}

  

 

技术分享

技术分享

技术分享

技术分享

 

就是一个爆搜,但这种有一次性物品的需要记录状态和回溯。

 

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int inf = 1<<30;
int ans = inf;
int hash[1010][30][100],T,n,m,h,S;
const int dx[] = {-1,1,0,0};
const int dy[] = {0,0,-1,1};
#define unlegal(x,y) x<0 || x>=n || y<0 || y>=m
char map[20][20];
void dfs(int pos,int hp,int kill){
	if(hp < 0)return;
	if(kill > ans)return;
	if(hash[pos][hp][kill] == T)return;
	hash[pos][hp][kill] = T;
	int x = pos/m,y = pos%m;
	for(int i = 0;i < 4;++i){
		int _x = x+dx[i], _y = y+dy[i];
		if(unlegal(_x,_y))continue;
		if(map[_x][_y] == ‘#‘)continue;
		if(map[_x][_y] == ‘.‘ && hash[_x*m+_y][hp][kill]!=T)dfs(_x*m+_y,hp,kill);
		if(map[_x][_y] == ‘M‘){
			map[_x][_y] = ‘.‘;
			dfs(_x*m+_y,hp-1,kill+1);
			map[_x][_y] = ‘M‘;
		}
		if(map[_x][_y] == ‘C‘ && hash[_x*m+_y][hp+5][kill]!=T){
			map[_x][_y] = ‘.‘;
			dfs(_x*m+_y,hp+5,kill);
			map[_x][_y] = ‘C‘;
		}
		if(map[_x][_y] == ‘E‘){
			ans = min(ans,kill);return;	
		}
	}
}

int main(){
	freopen("tower.in","r",stdin);
	freopen("tower.out","w",stdout);
	while(scanf("%d%d%d",&h,&n,&m)!=EOF){
		++T;
		ans = inf;
		for(int i = 0;i < n;++i){
			scanf("%s",map[i]);
			for(int j = 0;j < m;++j){
				if(map[i][j] == ‘S‘)S = i*m+j,map[i][j] = ‘.‘;
			}
		}
		dfs(S,h,0);
		if(ans == inf)puts("Poor Warrior");
		else printf("%d\n",ans);
	}
	return 0;
}

  

 

技术分享

技术分享

 

这个题首先分析题目,意思是要求裁判在两点之间并且水平也在两人之间,那么对于每一个人都可以作为一个裁判,那么假设在这个人在i这个点,i之前有x个人水平比他低,那么有i-x-1个人的水平比他高,后面同理,i之后有y个人水平比他低,那么就有n-y-i个人比他高,那么答案就是(n-y-i)*(x)+(i-x-1)*y,怎么维护一段区间比R数小的数的个数呢?很容易想到树状数组。

 

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 200010;
#define clr(a,b) memset(a,b,sizeof(a))
#define lowbit(i) i&-i
long long T,n,a[N],x[N],y[N];
struct bit{
	int c[N];
	void init(){clr(c,0);}
	void update(int x){
		for(int i = x;i <= N;i += lowbit(i)){
			c[i] += 1;
		}
	}
	int query(int x){
		int sum = 0;
		for(int i = x;i >= 1;i -= lowbit(i)){
			sum += c[i];
		}
		return sum;
	}
}f,b;

int main(){
	freopen("inhouse.in","r",stdin);
	freopen("inhouse.out","w",stdout);
	scanf("%I64d",&T);
	while(T--){
		f.init(),b.init();
		clr(a,0),clr(x,0),clr(y,0);
		scanf("%d",&n);
		for(int i = 1;i <= n;++i)scanf("%I64d",&a[i]);
		for(int i = 1;i <= n;++i){
			x[i] = f.query(a[i]);
			f.update(a[i]);
		}
		for(int i = n;i >= 1;--i){
			y[i] = b.query(a[i]);
			b.update(a[i]);
		}
		long long ans = 0;
		for(int i = 1;i <= n;++i){
			ans = ans+(i-x[i]-1)*y[i]+(n-i-y[i])*x[i];
		}
		cout<<ans<<endl;
	}
	return 0;
}

  

 

NOIP hzwer second - xgtao -

标签:

原文地址:http://www.cnblogs.com/xgtao984/p/5724111.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!