Samara SAU ACM ICPC Quarterfinal Qualification Contest 2012

Samara SAU ACM ICPC Quarterfinal Qualification Contest 2012

D

题意

把一个数每次取走一个因子,直至1为止,取不同的因子算不同的方案,问有几种方案。

思路

可以推出递推式dp【x】=所有因子方案数之和
特别提示:
1,用因子成对存在优化一个根号n。
2,不能用两层for算出1到k的所有方案,会超时。应该用记忆化搜索,复杂度和因子总数有关

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
inline long long read()
{
	long long kk=0,f=1;
	char cc=getchar();
	while(cc<'0'||cc>'9'){if(cc=='-')f=-1;cc=getchar();}
	while(cc>='0'&&cc<='9'){kk=(kk<<1)+(kk<<3)+cc-'0';cc=getchar();}
	return kk*f;
}
LL dp[1011111];
int dfs(int x)
{
	if(dp[x])return dp[x];
	dp[x]=1;
	for(int i=2;i<=x/i;++i)
	{
		if(x%i)continue;
		if(i==x/i)dp[x]+=dfs(i);
		else dp[x]+=dfs(i)+dfs(x/i);
	}
	return dp[x];
}
int main()
{
	int k=read();
	dp[1]=1;
	cout<<dfs(k);
} 

G

题意

给一串字符,要求没有重复的字母,对于重复的字母按照字典序,找到没用过的字母代替

思路

显然,只要长度不超过26就可以完成,反之不行;
用vis数组记录用过的字母,a记录下一个可以代替的字母是哪一个。遍历一次,重复了就让a上,并更新a。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
inline long long read()
{
	long long kk=0,f=1;
	char cc=getchar();
	while(cc<'0'||cc>'9'){if(cc=='-')f=-1;cc=getchar();}
	while(cc>='0'&&cc<='9'){kk=(kk<<1)+(kk<<3)+cc-'0';cc=getchar();}
	return kk*f;
}
bool vis[33],check[33];
int main()
{
	string ss;cin>>ss;
	for(int i=0;i<ss.length();++i)vis[ss[i]-'a'+1]=1;
	if(ss.length()>=27)
	{
		printf("IMPOSSIBLE");return 0;
	}
	int a=1;while(vis[a])a++;
	for(int i=0;i<ss.length();++i)
	{
		if(check[ss[i]-'a'+1])
		{
			ss[i]='a'+a-1;vis[a]=1;while(vis[a])a++;
			continue;
		}
		check[ss[i]-'a'+1]=1;
	}
	cout<<ss;
} 

k

题意

在末尾补充括弧,让他们可以成双成对

思路

遍历统计“(”,‘)’的个数,出现‘)’时更多说明非法。
否则在遍历完后再末尾加’)’

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
inline long long read()
{
	long long kk=0,f=1;
	char cc=getchar();
	while(cc<'0'||cc>'9'){if(cc=='-')f=-1;cc=getchar();}
	while(cc>='0'&&cc<='9'){kk=(kk<<1)+(kk<<3)+cc-'0';cc=getchar();}
	return kk*f;
}
string ss;
int main()
{
	cin>>ss;int asd=0;
	for(int i=0;i<ss.length();++i)
	{
		if(ss[i]=='(')asd++;
		else if(ss[i]==')')asd--;
		if(asd<0)
		{
			printf("IMPOSSIBLE");return 0;
		}
	}
	cout<<ss;
	for(int i=1;i<=asd;++i)cout<<')';
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值