Problem A
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
思路:最朴素的想法就是每次询问就把字符串copy出来,然后根据公式计算。但是时间复杂度明显是O(Nlen)所以会超时,我们可以发现有很多询问区间是重复的,所以可以选择先做预处理把结果先保存到一个数组中,由于要mod,所以要用到乘法逆元。
Ps:
逆元 :(a/b) (mod N) = (a * x) (mod N)。 x表示b的逆元。并且 b*x ≡ 1 (mod N ) 注意:只有当b与N互质的时候才存在逆元。一般情况下,ax+by=1;得 x为a mod b 的逆元,y为 b mod a的逆元。
根据费马小定理,对于素数n,任意不是n的倍数的b,都有: b^(N-1)=1(mod N)---->b*b^(N-2)=1(mod N)----->b的逆元为b^(N-2),
所以(
a/b)mod N =(a*b^(N-2))mod N
#include
#include
#define LL long long
#define mo 9973
using namespace std;
LL qmod(LL a,LL b)
{
LL sum=1;
while(b)
{
if(b&1) sum=(sum*a)%mo;
b>>=1;
a=(a*a)%mo;
}
return sum;
}
int main()
{
int n,i,a,b;
string str;
LL s[100005];
while(scanf("%d",&n)!=EOF)
{
cin>>str;
s[0]=1;
for(long i=1;i<=str.length();i++)
s[i]=(s[i-1])*(str[i-1]-28)% mo;
for(int i=0;iscanf("%d%d",&a,&b);
if(a>b) swap(a,b);
printf("%ld\n",(s[b]*(qmod(s[a-1],mo-2)%mo))%mo);
}
}
return 0;
}
Problem B
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
思路:看见1,3,8不自觉的就想起了Fibonacc,接着推了推就肯定了。不过看数据量,所以需要用高精度。
#include
#include
#define LL long long
LL a[205][100];
void add(int p,int q)
{
int n1[100],n2[100],n3[100];
memset(n1, 0, sizeof(n1));
memset(n2, 0, sizeof(n2));
memset(n3, 0, sizeof(n3));
for(int i=0;i<=a[p][0];i++) n1[i]=a[p][i];
for(int i=0;i<=a[q][0];i++) n2[i]=a[q][i];
if(n1[0]>n2[0]) n3[0]=n1[0];
else n3[0]=n2[0];
for(int i=1;i<=n3[0];i++)
{
n3[i]+=n1[i]+n2[i];
n3[i+1]+=n3[i]/10;
n3[i]=n3[i]%10;
}
while(n3[n3[0]+1]!=0) n3[0]++;
a[p+1][0]=n3[0];
for(int i=1;i<=n3[0];i++) a[p+1][i]=n3[i];
}
int main()
{
int n,i;
a[0][0]=0;
a[1][0]=1;a[1][1]=1;a[2][0]=1;a[2][1]=2;
for(i=3;i<=201;i++) add(i-1,i-2);
while(scanf("%d",&n)!=EOF)
{
for(int j=a[n][0];j>=1;j--) printf("%d",a[n][j]);
printf("\n");
}
return 0;
}
Problem C
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
思路:看见这个前缀查找就很自然的想起了Trie树,这个题就是一个简单模板题。
#include
#include
using namespace std;
typedef struct node
{
int num;
node *next[30];
node()
{
memset(next,0,sizeof(next));
num=0;
}
}Trie;
void insert(node *root,string s)
{
node *p=root;
int i=0;
while(s[i])
{
int x=s[i]-'a';
if(p->next[x]==0) p->next[x]=new node();
p=p->next[x];
p->num++;
i++;
}
}
int search(node *root,string s)
{
node *p=root;
int i=0;
while(s[i])
{
int x=s[i]-'a';
if(p->next[x]==0) return 0;
p=p->next[x];
i++;
}
return p->num;
}
void delet(node *root,string s,int k)
{
node *p=root;
int i=0;
while(s[i])
{
int x=s[i]-'a';
p=p->next[x];
p->num-=k;
i++;
}
for(i=0;i<30;i++) p->next[i]=0;
}
int main()
{
int i,n;
char s1[35],s2[35];
scanf("%d",&n);
Trie *root = new node();
for(i=0;iscanf("%s%s",s1,s2);
if(s1[0]=='i') insert(root,s2);
else if(s1[0]=='d')
{
int k = search(root,s2);
if(k!=0) delet(root,s2,k);
}else if(s1[0]=='s')
{
int k = search(root,s2);
if(k!=0) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}
Problem D
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
思路:直接对每次读入的名字排序,然后map记录就ok.
#include
#include
#include
#include
using namespace std;
int main()
{
int n;
map<string,int> name_count;
scanf("%d",&n);
for(int i=0;ichar s[45];
scanf("%s",s);
sort(s,s+strlen(s));
printf("%d\n",name_count[s]++);
}
return 0;
}
Problem E
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
思路:这道题比较繁琐,是个模拟题。每一行的每个变量表示一个集合,某个变量集合为空,则整个语句都为空,否则各变量分别对应一个集合。
#include
#include
#include
#include
using namespace std;
#define INF 20000
struct Expr
{
string var;
int l,r;
Expr()
{
this->l=-INF;
this->r=INF;
}
};
vector exprs[1005];
bool flag[1005];
void SkipSpace(const char *&str)
{
while(*str && (*str==' ')||(*str==',')) ++str;
}
bool GetMixedRange(int l1,int r1,int l2,int r2,int &l,int &r)
{
l=max(l1,l2);
r=min(r1,r2);
return l1<=l2;
}
void AddExpr(int k,Expr obj)
{
for(int i=0;iif(exprs[k][i].var == obj.var)
{
int l,r;
if(GetMixedRange(exprs[k][i].l,exprs[k][i].r,
obj.l,obj.r,l,r))
{
exprs[k][i].l=l;
exprs[k][i].r=r;
}
else flag[k]=false;
}
return;
}
exprs[k].push_back(obj);
}
bool Judge(Expr &a,Expr &b)
{
if(a.var != b.var) return true;
int l=max(a.l,b.l),r=min(a.r,b.r);
return l<=r;
}
void InitExpr(string str,int k)
{
const char *s = str.c_str();
while(*s)
{
string var,opr;
int num=0;
SkipSpace(s);
while(isalpha(*s))
{
var+=*s;
++s;
}
SkipSpace(s);
while(*s!=' '&&!isdigit(*s))
{
opr+=*s;
++s;
}
SkipSpace(s);
while(*s&&isdigit(*s))
{
num=num*10+*s-'0';
++s;
}
Expr obj;
obj.var = var;
if(opr =="<") obj.r=num-1;
else if(opr==">") obj.l=num+1;
else if(opr=="<=") obj.r=num;
else if(opr==">=") obj.l=num;
else if(opr=="==") obj.l=obj.r=num;
AddExpr(k,obj);
if(!flag[k])
{
printf("unique\n");
return;
}
}
vector<int> result;
for(int i=0;iif(!flag[i])continue;
bool ok=true;
for(int j=0;jfor(int p=0;pif(!Judge(exprs[i][j],exprs[k][p]))
{
ok=false;
break;
}
}
if(!ok) break;
}
if(ok) result.push_back(i+1);
}
int len=result.size();
if(len==0) puts("unique");
else
{
for(int i=0;iprintf("%d%c",result[i],i==len-1?'\n':' ');
}
}
int main()
{
int n;
string str;
scanf("%d",&n);
for(int i=0;itrue;
getline(cin,str);
for(int i=0;icin,str);
InitExpr(str,i);
}
return 0;
}