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;
}