2016弱校联萌十一专场10.5

A.

因为字符串不可以交叉,其实容易解

把不同字符的可用区域看成一个区间,用类似于链表的方法连接起来

查询的就是查询到的链表数量/4(当然右区间必须属于y)

区间查询用倍增或线段树都可以

//倍增
#include <cstdio>
#include <cstring>

char s[100005];
int m, n, pe, pa, ps, py, dep;
int pre[100005], ed[100005];
int fa[100005][20];

int main() {
    scanf("%s", s);
    scanf("%d", &m);
    n = strlen(s);
    for (int i = 0; i < n; ++i) {
        if (s[i] == ‘e‘) {
            pre[i + 1] = py;
            pe = i + 1;
        }
        if (s[i] == ‘a‘) {
            pre[i + 1] = pe;
            pa = i + 1;
        }
        if (s[i] == ‘s‘) {
            pre[i + 1] = pa;
            ps = i + 1;
        }
        if (s[i] == ‘y‘) {
            pre[i + 1] = ps;
            py = i + 1;
        }
        ed[i + 1] = py;
    }
    for (int i = 1; i <= n; ++i) fa[i][0] = pre[i];
    for (dep = 1; 1 << dep < n; ++dep);
    for (int i = 1; i < dep; ++i)
        for (int j = 1; j <= n; ++j)
            fa[j][i] = fa[fa[j][i - 1]][i - 1];
    for (; m--;) {
        int l, r;
        scanf("%d%d", &l, &r);
        int x = ed[r];
        int res = 1;
        for (int i = dep - 1; i >= 0; --i) {
            if (fa[x][i] >= l) {
                x = fa[x][i];
                res += 1 << i;
            }
        }
        printf("%d\n", res / 4);
    }
    return 0;
}

F.

求f(f(n))%20160519,其中f(0)=0 f(1)=1 f(i)=f(i-1)+f(i-2)

fib数列其实有循环节的,当运行到f(k-1)%k==k-1 f(k)==1 那循环节就是k

顺带补下这种数列的循环节知识:

当模数是质数模5余1或4,则这种数是5的二次剩余,则循环节是p-1的因子

当模数是质数模5余2或3,则这种数是5的二次非剩余,则循环节是2p+2的因子

当模数是合数,p=p1^a1*p2^a2*.....

可以想到积性函数,循环节是lcm(p1^(a1-1)*(p1的对应循环节数)*p2^(a2-1)*(p2的对应循环节数)*...)

lcm(...)是里面所有数的最小公倍数

然后快速幂一波AC

I.

题意:求出[l,r]所有单调不递增||单调不递减数

数位dp,没得说的,注意常数太大,o(10logn)会超时

所以就愉快地记忆化搜索,把指定位置是包括0~9位的全部填上

或者直接开场直接处理9、99、999...这些数的对应计数

这样就可以o(logn)胡搞了

果然不应该搞这么久的。。。比赛哪有那么多时间给你搞

以上是标准做法,已AC,我的非主流做法在下:

我是想用前缀和把搜索过程的复杂度压缩一下的,结果WA

大神求教

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<stdlib.h>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#include<assert.h>
using namespace std;
typedef long long ll;
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}

ll fac[21];
ll tal[20][10][2],pre[20][10][2];
//0:down,1:all
ll f(int n){return n<0?0:fac[n];}
void gettal()
{
    fac[0]=1;
    memset(tal,0,sizeof(tal));
    memset(pre,0,sizeof(pre));
    int i,j;
    for(i=1;i<21;i++)fac[i]=fac[i-1]*i;
    for(i=0;i<10;i++)tal[0][i][1]=1,tal[0][i][0]=0,pre[0][i][1]=pre[0][i][0]=i+1;
    for(i=1;i<20;i++)
    {
        for(j=0;j<10;j++)
        {
            tal[i][j][0]=j==0?0:f(i+j-1)/f(j-1)/f(i);
            tal[i][j][0]+=tal[i-1][j][0];

            tal[i][j][1]=tal[i][j][0]+tal[i-1][j][1]-tal[i-1][j][0];
            tal[i][j][1]+=j==9?0:f(8-j+i)/f(8-j)/f(i);

            pre[i][j][0]=j?pre[i][j-1][0]+tal[i][j][0]:tal[i][j][0];
            pre[i][j][1]=j?pre[i][j-1][1]+tal[i][j][1]:tal[i][j][1];
        }
    }
}
ll solve(ll n)
{
    if(!n)return 1;
    int i,j,path,ph;
    ll tmp,ans=0;
    for(i=0,tmp=1;n>=tmp;i++,tmp*=10);i--;tmp/=10;
    int stat=1;
    path=n/tmp;
    ans+=pre[i][path-1][1]-pre[i][0][1];
    tmp/=10;
    for(i--;i>0;i--)
    {
        ans+=pre[i][9][1]-pre[i][0][1];
        ph=(n%(tmp*10))/tmp;
        if(stat==1)//keep
        {
            if(path>ph){stat=0;if(ph)ans+=pre[i][ph-1][0]+ph;}
            else if(path==ph){if(ph)ans+=pre[i][ph-1][0]+ph;}
            else
            {
                stat=2;
                ans+=pre[i][ph-1][0]+ph;
                ans+=tal[i][ph][1],
                ans+=pre[i][ph-1][1]-pre[i][path][1];
                ans-=pre[i][ph-1][0]-pre[i][path][0];
            }
            path=ph;
        }
        else if(stat==2)//increase
        {
            if(path>ph)
            {
                stat=3;
                break;
            }
            ans+=pre[i][ph-1][1]-pre[i][path-1][1]-pre[i][ph-1][0]+pre[i][path-1][0];
            path=ph;
        }
        else if(stat==0 && path)//decrease
        {
            if(ph)ans+=pre[i][min(path,ph)-1][0]+min(path,ph);
            path=min(path,ph);
        }
        tmp/=10;
    }
    ans+=pre[0][9][1];
    ph=(n%(tmp*10))/tmp;
    if(stat==0)ans+=min(path,ph)+1;
    else if(stat==1)ans+=ph+1;
    else if(stat==2)ans+=max(0,ph-path+1);
    return ans;
}
int main()
{
    int t;
    ll l,r;
    gettal();
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld",&l,&r);
        printf("%lld\n",solve(r)-solve(l-1));
    }
    return 0;
}

J.

题意。。。实在难以描述,看https://acm.bnu.edu.cn/v3/statments/taiwan2016.pdf吧

这题一看像是多项式乘法,但是下面的不是加而是取其最大,所以什么fft,nft都可以歇歇了

其实也不难想到解法,把最大数填上对应位置,之后从大到小填,碰到已填元素就跳过

直到整个表都填满为止

为什么这样看似o(n^2)的解法不会超时。。。我也不知道。。。

写时SB了,数组开成10^5结果老RE

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<stdlib.h>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#include<assert.h>
using namespace std;
typedef long long ll;
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
int a[2][200060];
int occupy[200060];
int main()
{
    int n,j,i,t;
    memset(occupy,-1,sizeof(occupy));
    scanf("%d",&n);
    for(j=0;j<2;j++)
    {
        for(i=0;i<n;i++)
        {
            scanf("%d",&t);
            a[j][t]=i;
        }
    }
    int cnt=n;
    for(i=n*2-2;cnt;i--)
    {
        for(j=max(0,i-n+1);j<n && cnt;j++)
        {
            if(i<j)continue;
            if(i-j>=n)break;
            t=a[0][j]+a[1][i-j];
            if(occupy[t%n]==-1)occupy[t%n]=i,cnt--;
        }
    }
    for(i=0;i<n;i++)printf("%d%c",occupy[i],i==n-1?‘\n‘:‘ ‘);
    return 0;
}

时间: 2024-11-07 03:25:37

2016弱校联萌十一专场10.5的相关文章

2016弱校联萌十一专场10.3 遗憾题合集

http://acm-icpc.aitea.net/index.php?2016%2FPractice%2F%E6%A8%A1%E6%93%AC%E5%9C%B0%E5%8C%BA%E4%BA%88%E9%81%B8%2F%E8%AC%9B%E8%A9%95 C.We don't wanna work! @siludose 你要的代码,做好了参考看 SB模拟,xjb模拟 #include <iostream> #include <algorithm> #include <st

2016弱校联萌十一专场10.2

F.floyd-warshell 20000个点,距离为1的所有边求最短路 感觉就是单纯的生成树求最短路(最近公共祖先) 然后把去掉的边还原 把涉及的点bfs一下拼出最短路 #include<cstdio> #include<algorithm> #include<cstring> #define F(i,a,b) for(int i=a;i<=b;i++) #define mst(a,b) memset(a,b,sizeof(a)) using namespac

西南弱校联萌(1)

A. 垃圾题目毁我青春(3n+1猜想 || 模拟) Sample Input 5 Sample Output YES Hint 对于样例1:1 -> 2 -> 4 -> 8 -> 16 -> 5 Solve: 可以直接从n模拟(模拟就变成了3*n+1猜想了),所以很明显他是都是yes的 Code: 1 #pragma comment(linker, "/STACK:36777216") 2 3 #include <bits/stdc++.h>

(2016弱校联盟十一专场10.3) A.Best Matched Pair

题目链接 #include<cstdio> #include<cstring> #include<algorithm> #include<stack> using namespace std; int n,data[1005]; int cal(int x) { int tx=x; int pre=-1; while(tx) { if(pre!=-1&&tx%10-pre!=-1) return -1; pre = tx%10; tx/=10

2016弱校联盟十一专场10.3---Similarity of Subtrees(深搜+hash、映射)

题目链接 https://acm.bnu.edu.cn/v3/problem_show.php?pid=52310 problem description Define the depth of a node in a rooted tree by applying the following rules recursively: • The depth of a root node is 0. • The depths of child nodes whose parents are with

2016弱校联盟十一专场10.2---Around the World(深搜+组合数、逆元)

题目链接 https://acm.bnu.edu.cn/v3/problem_show.php?pid=52305 problem  description In ICPCCamp, there are n cities and (n−1) (bidirectional) roads between cities. The i-th road is between the ai-th and bi-th cities. It is guaranteed that cities are conne

2016弱校联盟十一专场10.2——Around the World

题目链接:Around the World 题意: 给你n个点,有n-1条边,现在这n-1条边又多增加了ci*2-1条边,问你有多少条欧拉回路 题解: 套用best定理 Best Theorem:有向图中以 i 为起点的欧拉回路个数为以 i 为根的树形图个数 ×(( 每个点 度数 −1)!). Matrix Tree Theorem:以 i 为根的树形图个数 = 基尔霍夫矩阵去掉第 i 行第 i 列的行列 式. 从某个点 i 出发并回到 i 的欧拉回路个数 = 以 i 为起点的欧拉回路个数 ×i

2016弱校联盟十一专场10.2部分题解

1/10 J. Matrix Transformation 1 /*zhen hao*/ 2 #include <bits/stdc++.h> 3 using namespace std; 4 5 #define lson l, m, rt*2 6 #define rson m + 1, r, rt*2+1 7 #define xx first 8 #define yy second 9 10 typedef long long LL; 11 typedef unsigned long lon

2016弱校联盟十一专场10.2——Floyd-Warshall

题目链接:Floyd-Warshall 题意: 给你n个点,m条边,100>m-n>0,现在有q个询问,问你任意两点的最短距离,题目保证每条边都被连接,每条边的距离为1 题解: 首先我们可以看到边最多只比点多100个,那么我们可以先将n-1条边生成一棵树,然后用LCA来求最短距离. 然而有可能最短路在多余的这100条边上,所以我们将这100条边的两个端点到所有点的最短路用bfs预处理出来, 然后再用来更新一下答案就行. 1 #include<cstdio> 2 #include&l