数论 + bfs Remider hdu1104

1 篇文章 0 订阅

给定 n,m,k(<1000)

定义的%:a = b * q + r (q > 0 and 0 <= r < q), then we have a % q = r. (取模后为正整数)

n可以+,-,*,% m, 求最少多少步骤可以使得 n%k = (初始的n+1)%k

思路:

bfs,最后的结果都要%k,避免数过大我们中途每次求得的值都要取%

但是中途也可能%m,所有我们可以先%(k*m) ,易证 a%m = a%(m*k)%m

k*m的范围也在1000000内这样是可行的

收获:

对于一个数取模的理解,取模满足+,-,*的线性运算,但是不满足%,/的运算

代码如下:


/*
ID: meixiny1
PROG: test
LANG: C++11
*/
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <string>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <cctype>
using namespace std;
typedef long long ll;
typedef pair<int ,int> pii;
#define MEM(a,b) memset(a,b,sizeof a)
#define CLR(a) memset(a,0,sizeof a);
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
#define PI 3.1415926
//#define LOCAL
char ch[4]={'+','-','*','%'};
struct node
{	
	int cnt;
	int which;
	int where;
	int last;
}dp[1000005];
bool vis[1000005];
void print(int now){
	if(dp[now].which==-1)return;
	print(dp[now].last);
	printf("%c",ch[dp[now].which]);
}
int main()
{
#ifdef LOCAL
	freopen("in.txt", "r", stdin);
//	freopen("out.txt","w",stdout);
#endif
	int n,k,m;
	while(cin >> n >> k >> m &&(n || k || m)){
		MEM(vis,0);
		for(int i=0;i<=1000000;i++)dp[i].cnt = inf;
		int ans = ((n+1)%k+k)%k;
		int end;
		node a,b; a.cnt = 0, a.which = -1, a.where = (n%(k*m)+k*m)%(k*m);
		vis[a.where] = 1;
		queue<node> q;
		q.push(a);
		int ok = 0;
		while(!q.empty()){
			a = q.front();q.pop();
			dp[a.where] = a;
			if(a.where%k == ans){
				ok = 1;
				end = a.where;
				break;
			}
			if(!vis[(a.where+m)%(k*m)])vis[(a.where+m)%(k*m)]=1,b.cnt = a.cnt+1, b.which = 0, b.where = (a.where+m)%(k*m), b.last = a.where, q.push(b);
			if(!vis[((a.where-m)%(k*m)+k*m)%(k*m)])vis[((a.where-m)%(k*m)+k*m)%(k*m)]=1,b.cnt = a.cnt+1, b.which = 1, b.where = ((a.where-m)%(k*m)+k*m)%(k*m), b.last = a.where, q.push(b);
			if(!vis[(a.where*m)%(k*m)])vis[(a.where*m)%(k*m)]=1,b.cnt = a.cnt+1, b.which = 2, b.where = (a.where*m)%(k*m), b.last = a.where, q.push(b);
			if(!vis[(a.where%m)%(k*m)])vis[(a.where%m)%(k*m)]=1,b.cnt = a.cnt+1, b.which = 3, b.where = (a.where%m)%(k*m), b.last = a.where, q.push(b);
		}
		if(ok){
			printf("%d\n",dp[end].cnt);
			print(end);
			printf("\n");
		}
		else{
			printf("0\n");
		}
	}
	return 0;
}










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值