TopCoder SRM 574

博客分享了几道算法题的题意与思路。div.1的T1是关于两个玩家对数字操作,判断A能否在1000步内使两数相同,思路是判断a中有无b或b翻转数的子串;T2是正N边形连点求方案数,用dp数组求解。div.2的T3与T2类似但数据范围更小。

div.1

T1

题意

有两个数字a,b
玩家A 持有a,玩家B 持有b
他们可以改变自己的数字 方式为

  1. 倒转
    2.除以10
    两人轮流进行操作 A先
    若在1000步以内可以使得两个数字相同 则A胜利 反之 A失败

思路

只要判断一下 a中有没有b或b的翻转数的子串 即可

//tc is healthy, just do it
#include <bits/stdc++.h>
using namespace std;

class TheNumberGame {
public:
    string determineOutcome( int A, int B );
};
inline int sol(int x)
{
	int s=0;
	while(x>0)
	{
		s=s*10+(x%10);
		x=x/10;
	}
	return s;
}
string TheNumberGame::determineOutcome(int a, int b) {
    int i,n;
    for(n=1;n<=b;n*=10);
    cout<<n<<" ";
    for(i=a;i;i/=10)
    	if(i%n==b) return "Manao wins";
    b=sol(b);
    for(i=a;i;i/=10)
    	if(i%n==b) return "Manao wins";
    return "Manao loses";
}
T2

题意

一个正N边形,按给出的顺序连起M个点,然后你按照顺序连起剩下的N-M个点。要求每次新连的线段必须与前面的线段相交。求全部连完回到起始点的方案数。

思路

定义dp[i][j]表示此时在i,取得点的集合为j。
发现,如果x想要到y,那么在圆上x顺时针到y或x逆时针到y一定都要有点。

#include <bits/stdc++.h>
using namespace std;
int n,m,vis[10010],tot;
long long d[18][1<<18];
vector<int> a;
class PolygonTraversal {
public:
    long long count( int N, vector <int> points );
};
int work(int now,int to,int s)
{
	int temp,l=0,r=0;
	temp=(to+1)%n;
	while(temp!=now)
		if(vis[temp]||s&(1<<temp))
		{
			l=1;
			break;
		}
		else temp=(temp+1)%n;
	temp=(now+1)%n;
	while(temp!=to)
		if(vis[temp]||s&(1<<temp))
		{
			r=1;
			break;
		}
		else temp=(temp+1)%n;
	if(l&&r) return 1;
	return 0;
}
long long sol(int p,int s,int cnt)
{
	long long &ans=d[p][s];
	if(ans) return ans;
	if(cnt==n) 
	{
		ans=work(p,a[0],s);
		return ans;
	}
	ans=0;
	for(int i=0;i<n;i++)
	{
		if(i==p||vis[i]||(s&(1<<i))) continue;
		if(work(p,i,s)) ans+=sol(i,s|(1<<i),cnt+1);
	}
	return ans;
}
long long PolygonTraversal::count(int N, vector <int> A) {
	int i;
	n=N;
	a=A;
	m=a.size();
	memset(vis,0,sizeof(vis));
	tot=0;
	for(i=0;i<m;i++) a[i]--,vis[a[i]]=1,tot+=(1<<a[i]);
	return sol(a[m-1],tot,m);
}

div.2

T3

此题与div.1的T2 相同 只是 数据范围更小了

参考上面即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值