2014西安区域赛

2014西安区域赛

K.Last Defences

参考题解

给定两个数A,B(<1e18)S0=A,S1=B,Si=| Si-1- Si-2 |,求Si不同值的个数

假设A=11,B=3,简单计算可得序列S:11,3,8,5,3,2,1,1,0,1,0~

仔细观察可以看出:8=11-1*3,5=11-2*3,2=11-3*3,3出现的次数为11%3-1,产生的新数字个数为A/B

那么1如何得来的:11%3=2,3-2=1;现在并不容易看出,但多检查几对数可以看出 1是由 B-(A%B)得到的

于是可以想到,一个递推过程DFS(A,B)=A/B+DFS(B,A%B)

其中几项要特判A==B==0,A==0||B==0,A==B,另外若A%B==0,假设A=4,B=2,它们所贡献的答案为除A和B本身之外有1,0,

其中的1时A-B,在A/B的时候已经计算过了所以需要减去,所以此时的贡献为A%B-1;

#include<bits/stdc++.h>
using namespace std;
long long A,B;
int t;
long long dfs(long long a,long long b)
{
    if(a%b==0) return a/b-1;
    long long x=a%b,y=a/b;
    return y+dfs(b,x);
}
int main()
{
    scanf("%d",&t);
    for(int tc=1;tc<=t;++tc)
    {
        scanf("%lld%lld",&A,&B);
        if(A==B&&A==0) {printf("Case #%d: 1\n",tc);continue;}
        if(A==B||A==0||B==0) {printf("Case #%d: 2\n",tc);continue;}
        printf("Case #%d: %lld\n",tc,dfs(A,B)+2);
    }
    return 0;
}

G.the problem to slow down you

给定两个字符串,求其相同的回文串的个数

2个回文自动机对着跑,答案为相同节点上回文串的乘积的和

#include<bits/stdc++.h>
using namespace std;
const int MAX=2e5+5;
struct Trie
{
    static const int MAXN=26;
    int nxt[MAX][MAXN],f[MAX],cnt[MAX],num[MAX],len[MAX],c[MAX],last,n,L;
    int newnode(int x)
    {
        for(int i=0;i<MAXN;++i) nxt[L][i]=0;
        cnt[L]=num[L]=0;len[L]=x;return L++;
    }
    void init()
    {
        L=0;newnode(0);newnode(-1);
        last=0;n=0;c[n]=-1;f[0]=1;
    }
    int getf(int x)
    {
        while(c[n-len[x]-1]!=c[n]) x=f[x];
        return x;
    }
    void add(int x)
    {
        c[++n]=x;
        int cur=getf(last);
        if(!nxt[cur][x])
        {
            int now=newnode(len[cur]+2);
            f[now]=nxt[getf(f[cur])][x];
            nxt[cur][x]=now;
            num[now]=num[f[now]]+1;
        }
        ++cnt[last=nxt[cur][x]];
    }
    void count()
    {
        for(int i=L-1;i>=2;--i) cnt[f[i]]+=cnt[i];
    }
}PT1,PT2;
char s1[MAX],s2[MAX];
int t;
long long dfs(int u,int v)
{
    long long tmp=0;
    for(int i=0;i<26;++i)
    {
        if(PT1.nxt[u][i]&&PT2.nxt[v][i])
        {
            tmp+=1ll*PT1.cnt[PT1.nxt[u][i]]*PT2.cnt[PT2.nxt[v][i]];
            tmp+=dfs(PT1.nxt[u][i],PT2.nxt[v][i]);
        }
    }
    return tmp;
}
int main()
{
    scanf("%d",&t);
    for(int tc=1;tc<=t;++tc)
    {
        scanf("%s%s",s1,s2);
        PT1.init();PT2.init();
        int L1=strlen(s1),L2=strlen(s2);
        for(int i=0;i<L1;++i) PT1.add(s1[i]-'a');
        for(int i=0;i<L2;++i) PT2.add(s2[i]-'a');
        PT1.count(),PT2.count();
        printf("Case #%d: %lld\n",tc,dfs(0,0)+dfs(1,1));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Nrtostp/article/details/83117333