A - Friendship of Frog
题意:两个相同字母的最小间隔
判断:水题
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,minn,N,num=0,flag;
cin>>N;
while(N--){
num++;
string str;
cin>>str;
n=str.length();
flag=0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
//cout<<str[i]<<str[j]<<endl;
if(flag==0&&str[i]==str[j])
{
minn=j-i;
flag=1;
}
else if(str[i]==str[j])
minn=min(minn,j-i);
}
}
if(flag==1)
cout<<"Case #"<<num<<": "<<minn<<endl;
else
cout<<"Case #"<<num<<": "<<"-1"<<endl;
}
}
B - Almost All Divisors
题意:
判断:对于一个数,他所有的因子是对称分布的,最小的与最大的相乘就为该数,次小的与次大的相乘也为该数,依次类推,那么我们只要根据已知条件求得原来的数是多少,然后再判断该数的所有因子除了1和本身是否都在所给信息中存在并且除了1和本身它的因子个数也应等于给出来的n,判断输出即可。
#include<bits/stdtr1c++.h>
using namespace std;
int n,m;
long long int a[100005],b[100005];
int main()
{
int t;
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
sort(a+1,a+1+n);
long long int ans=a[1]*a[n];
int flag=1;
for(int i=2;i<=(n+1)/2;i++){
if(a[i]*a[n-i+1]!=ans){
flag=0;
break;
}
}
if(flag==0){
cout<<-1<<endl;
continue;
}
int num=0;
for(long long int i=2;i*i<=ans;i++){
if(ans%i==0){
if(i*i==ans)num++;
else num+=2;//必定配对
}
}
if(num!=n)
cout<<-1<<endl;
else
cout<<ans<<endl;
}
return 0;
}
C - Land of Farms
题意:N*M的图中有一些旧农场,现在要建立一些新的农场,如果新的农场覆盖了某一个旧的农场中的一个点,它就必须覆盖整个这个旧农场。现在要建立尽可能多的新农场,使得每个新农场之间都不相邻,求最多能建立多少个新农场。
判断:最大独立集问题,代码先贴在这,其实嘞,我没看懂
#include<cstdio>
using namespace std;
#define M 130
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};
char ch[M];
int num[M][M],a[M][M],set[M][M],f[M][M],g[M],p[M],ans;
bool dfs(int size,int dep)
{
if(!size)
{
if(dep>ans)
{
ans=dep;
return 1;
}
else return 0;
}
for(int i=1;i<=size;i++)
{
if(dep+size-i+1<=ans) return 0;
int u=set[dep][i];
if(dep+g[u]<=ans) return 0;
int num=0;
for(int j=i+1;j<=size;j++)
if(f[u][set[dep][j]]) set[dep+1][++num]=set[dep][j];
if(dfs(num,dep+1)) return 1;
}
return 0;
}
int main()
{
int T,n,m,size,id;
scanf("%d",&T);
for(int v=1;v<=T;v++)
{
scanf("%d%d",&n,&m);//n行m列
for(int i=0;i<=9;i++) p[i]=0;//用于记录每个古田的地的大小
id=0;
for(int i=1;i<=n;i++)
{//以行做循环
scanf("%s",ch+1);//把一行作为字符串读入
for(int j=1;j<=m;j++)//一行第几个字符
{
if('0'<=ch[j]&&ch[j]<='9')//如果是数字,就属于古田
{
if(!p[ch[j]-'0'])
p[ch[j]-'0']=++id;//相对应的古田地皮量增加
num[i][j]=p[ch[j]-'0'];//把古田的位置进行记录,ij是古田,并其值为到此为止该古田的数量
}
else num[i][j]=++id;//
}
}
for(int i=1;i<=id;i++)
for(int j=1;j<=id;j++)
f[i][j]=i!=j;//==if i!=j f[i][j]=1 else f[i][j]=0,优先运算级问题
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
for(int k=0;k<=3;k++)
{
int x=i+dx[k];
int y=j+dy[k];
if(x<1||x>n||y<1||y>m) continue;
f[num[i][j]][num[x][y]]=0;
f[num[x][y]][num[i][j]]=0;
}
}
ans=0;
for(int i=id;i>0;i--)
{
size=0;
for(int j=i+1;j<=id;j++)
if(f[i][j]) set[1][++size]=j;
dfs(size,1);
g[i]=ans;
}
printf("Case #%d: %d\n",v,ans);
}
return 0;
}
D - String
题意:输入M,L和str字符串,计算str的不同“可恢复”子字符串的数量。我们认为S的子字符串是“可恢复的”,当且仅当
(i)长度M*L;
(ii)它可以通过连接S的M个“多样化”子串来构造,其中每个子串的长度为L; 如果两个字符串的每个位置不具有相同的字符,则认为它们是“多样化的”。
判断:哈希算法,也算是二分匹配的一种,这种算法的难点在于key的决定要使得冲突最小,而这道题的代码问题在于mp[x]到底是什么,为什么判断数量到达m就是符合条件
#include<bits/stdtr1c++.h>
#define ull unsigned long long
using namespace std;
char s[100100];
ull hsh[100100],p[100100];
map<ull,int> mp;
//哈希的核心就是一个key一个value对应好,然后防止冲突,这个key的取值是难点
int gethash(int l,int r)//以长度为l分割字符串后,每个子字符串的第一个字符和最后一个字符
{
return hsh[r]-hsh[l-1]*p[r-l+1];//key值由最后一个字符的hsh和第一个字符往前走一个的hsh以及字符串长度对应的value构成
}
int main()
{
int m,l;
while(cin>>m>>l)//M,L
{
scanf("%s",s+1);//输入字符串,这里为什么要加一呢
int num=0;
int len=strlen(s+1);//取得字符串长度
p[0]=1;//寄存value的数组
for(int i=1;i<=len;i++)
{
hsh[i]=hsh[i-1]*131+s[i]-'a'+1;//每个字母的一个特定hsh,因为跟前一个hsh挂钩,所以即使字母是一样的,也不会重复
p[i]=p[i-1]*131;//同样也是与前者挂钩,防止冲突
}
for(int i=1;i<=l&&i+m*l<=len;i++)//这个循环这里我还不太明白
{
mp.clear();//map归零
for(int j=i;j<i+m*l;j+=l)//以l为单位
{
ull x=gethash(j,j+l-1);//小单位长度为l的子字符串的第一个和最后一个字母去生成key
mp[x]++;//记录到map里
}
if(mp.size()==m)//map里存的此时为总数
num++;
for(int j=i+m*l;j+l-1<=len;j+=l)
{
ull x=gethash(j,j+l-1);
mp[x]++;
ull y=gethash(j-m*l,j-m*l+l-1);
mp[y]--;
if(mp[y]==0) mp.erase(y);//把上一个记得y删去
if(mp.size()==m) num++;//如果mp记录的数据组有m个则
}
}
cout<<num<<endl;//符合要求不重复的子字符串的数量,计算S的不同“可恢复”子字符串的数量。
}
return 0;
}
E - Chat
题意:一个渣男按要求处理女朋友们的故事
判断:第一反应感觉很像链表,但其实吧好像数组也能完成,就是没有什么算法,只要有序列就可以了,细节太多写写很烦
代码贴在这里啦
#include<bits/stdtr1c++.h>
using namespace std;
const int N = 5005;
const int M = 100005;
const int inf = 1000000007;
const int mod = 1000000007;
map<int,int> m;
list<int> l;
int p,top;
__int64 ans[N];
void Add(int u)
{
if(m[u])
{
puts("same priority.");
return ;
}
puts("success.");
m[u]=p++;
l.push_back(u);
}
void Close(int u)
{
if(!m[u])
{
puts("invalid priority.");
return ;
}
printf("close %d with %I64d.\n",u,ans[m[u]]);
m[u]=0;
l.remove(u);
if(top==u)
top=0;
}
void Chat(int w)
{
if(l.empty())
{
puts("empty.");
return ;
}
puts("success.");
if(top)
ans[m[top]]+=w;
else
ans[m[l.front()]]+=w;
}
void Rotate(int x)
{
if(x<1||x>l.size())
{
puts("out of range.");
return ;
}
puts("success.");
list<int>::iterator it;
int i;
for(i=1,it=l.begin();it!=l.end()&&i<x;it++,i++);
//printf("%d\n",*it);
int tmp=*it;
l.erase(it);
l.push_front(tmp);
}
void Prior()
{
if(l.empty())
{
puts("empty.");
return ;
}
int i,x,Max=0;
list<int>::iterator it;
for(i=1,it=l.begin();it!=l.end();it++,i++)
if(*it>Max)
Max=*it,x=i;
Rotate(x);
}
void Choose(int u)
{
if(!m[u])
{
puts("invalid priority.");
return ;
}
int x;
list<int>::iterator it;
for(x=1,it=l.begin();it!=l.end();it++,x++)
if(*it==u)
break;
Rotate(x);
}
void Top(int u)
{
if(!m[u])
{
puts("invalid priority.");
return ;
}
puts("success.");
top=u;
}
void Untop()
{
if(!top)
{
puts("no such person.");
return ;
}
puts("success.");
top=0;
}
char s[10];
int main()
{
int t,n,i,u,w,x;
scanf("%d",&t);
while(t--)
{
p=1;top=0;
m.clear();
l.clear();
memset(ans,0,sizeof(ans));
scanf("%d",&n);
for(i=1;i<=n;i++)
{
printf("Operation #%d: ",i);
scanf("%s",s);
if(!strcmp(s,"Add"))
{
scanf("%d",&u);
Add(u);
}
else if(!strcmp(s,"Close"))
{
scanf("%d",&u);
Close(u);
}
else if(!strcmp(s,"Chat"))
{
scanf("%d",&w);
Chat(w);
}
else if(!strcmp(s,"Rotate"))
{
scanf("%d",&x);
Rotate(x);
}
else if(!strcmp(s,"Prior"))
Prior();
else if(!strcmp(s,"Choose"))
{
scanf("%d",&u);
Choose(u);
}
else if(!strcmp(s,"Top"))
{
scanf("%d",&u);
Top(u);
}
else if(!strcmp(s,"Untop"))
Untop();
}
if(top&&ans[m[top]])
printf("Bye %d: %I64d\n",top,ans[m[top]]);
list<int>::iterator it;
for(it=l.begin();it!=l.end();it++)
if(*it!=top&&ans[m[*it]])
printf("Bye %d: %I64d\n",*it,ans[m[*it]]);
}
return 0;
}