2019-2020nowcoder牛客寒假基础1

A.honoka和格点三角形

题意:记录至少有一条边与X轴或者是Y轴平行的面积为1的网格三角形个数

思路:由于是网格三角形,分类讨论,以平行坐标轴的边作为底边,三角形的底边分为2或者1两种情况

就以代码中s1为例子,以2为底边,与格点数为n的一边(x==1)平行,底边的横坐标可能在x = 2,3,4...m-1(即(m-2))的地方,高为1有向右或者是向左两种情况,

再考虑底边的纵坐标,n个点里选出连续3个点的方案有n-2种,三角形的顶点有n种可能性,反正平行底边的都是,再加上左右两边的情况。

接下来每一种都差不多,就是要考虑直角三角形的情况

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <stack>

using namespace std;
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scl(a) scanf("%lld",&a)
#define scll(a,b) scanf("%lld%lld",&a,&b)
#define prl(a) printf("%lld\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",a)
#define ptd(a) printf("%d ",a)
#define scf(a) scanf("%lf",&a)
#define scff(a,b) scanf("%lf%lf",&a,&b)
#define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
#define rint register int
#define mem(a) memset(a,0,sizeof(a))
#define rush() int T;scd(T);while(T--)
#define lc(i) (i<<1)
#define rc(i) (i<<1|1)
#define mp make_pair
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef double db;
const ll mod = 1e9 + 7;
inline int read() {
    char c=getchar();
    int x=0,f=1;
    while(c<'0'||c>'9') {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
ll n, m;
int main () {
    scll(n, m);
    ll s1 = (2 * (m - 2)%mod * (n - 2)%mod * n%mod + 2 * n%mod * (n - 2)%mod)%mod;
    ll s2 = (2 * (n - 2)%mod * (m - 2)%mod * m%mod + 2 * m%mod * (m - 2)%mod)%mod;
    ll s3 = (2 * (n - 2)%mod * (m - 1)%mod * (m - 2)%mod)%mod;
    ll s4 = (2 * (m - 2)%mod * (n - 1)%mod * (n - 2)%mod)%mod;
    ll ans = (((s1+s2)%mod+s3)%mod+s4)%mod;
    prl(ans);
    return 0;
}
View Code

B.kotori和bangdream

小学概率签到奈何我没手没眼做的时候已经过穿了

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <stack>

using namespace std;
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scl(a) scanf("%lld",&a)
#define scll(a,b) scanf("%lld%lld",&a,&b)
#define prl(a) printf("%lld\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",a)
#define ptd(a) printf("%d ",a)
#define scf(a) scanf("%lf",&a)
#define scff(a,b) scanf("%lf%lf",&a,&b)
#define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
#define rint register int
#define mem(a) memset(a,0,sizeof(a))
#define rush() int T;scd(T);while(T--)
#define lc(i) (i<<1)
#define rc(i) (i<<1|1)
#define mp make_pair
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef double db;
inline int read() {char c=getchar();int x=0,f=1;while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}return x*f;}
const int inf = 2147483647-1;
const int maxn = 1e5 + 10;
const ll mod = 1e9 + 7;
int main ()
{
    int n, x, a, b;
    n = read(), x = read(), a = read(), b = read();
    db ans = 0.01*(n * a * x + n * b * (100 - x));
    printf("%.2lf\n",ans);
    return 0;
}
View Code

C.umi和弓道

题意:umi站在(x0,y0),有一块在坐标轴上的挡板,挡掉以后她可以射的不超过k个靶子,求挡板的最小值

思路:分成板子放在y轴和x轴讨论,以y轴为例,对靶子的x进行sort,统计在umi另一端的靶子个数同时并计算出截距,判断是否有解再滚动数组

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <stack>

using namespace std;
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scl(a) scanf("%lld",&a)
#define scll(a,b) scanf("%lld%lld",&a,&b)
#define prl(a) printf("%lld\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%.8lf\n",a)
#define ptd(a) printf("%d ",a)
#define scf(a) scanf("%lf",&a)
#define scff(a,b) scanf("%lf%lf",&a,&b)
#define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
#define rint register int
#define mem(a) memset(a,0,sizeof(a))
#define rush() int T;scd(T);while(T--)
#define lc(i) (i<<1)
#define rc(i) (i<<1|1)
#define mp make_pair
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef double db;
inline int read() {
    char c=getchar();
    int x=0,f=1;
    while(c<'0'||c>'9') {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
const int inf = 2147483647-1;
const db  infdb = 1.78e+308;
const int maxn = 1e5 + 10;
const ll mod = 1e9 + 7;
struct pos{
    int x, y;
}p[maxn], st;
db k(pos a, pos b) {
    return 1.0 * (a.y - b.y) / (a.x - b.x);
}
db m(pos a, pos b) {
    return 1.0 * (a.x - b.x) / (a.y - b.y);
}
bool cmp1(pos &a, pos &b) {
    return a.x < b.x;
}
bool cmp2(pos &a, pos &b) {
    return a.y < b.y;
}
int n, kk;
db solve1() {
    vector<db> v;
    if (st.x > 0) {
        for (int i = 1; i <= n; ++i) {
            if (p[i].x > 0) continue;
            db kx = k(st, p[i]);
            v.push_back(st.y + kx * (0 - st.x));
        }
    } else {
        for (int i = 1; i <= n; ++i) {
            if (p[i].x < 0) continue;
            db kx = k(st, p[i]);
            v.push_back(st.y + kx * (0 - st.x));
        }
    }
    int sz = v.size();
    if (n - sz > kk) return -1;
    sort(v.begin(), v.end());
    db res = infdb;
    int len = min(n - kk, sz);
    for (int i = 0; i <= v.size()-len; ++i) {
        res = min(res, v[i + len - 1] - v[i]);
    }
    return res;
}
db solve2() {
    vector<db> v;
    if (st.y > 0) {
        for (int i = 1; i <= n; ++i) {
            if (p[i].y > 0) continue;
            db my = m(st, p[i]);
            v.push_back(st.x + my * (0 - st.y));
        }
    } else {
        for (int i = 1; i <= n; ++i) {
            if (p[i].y < 0) continue;
            db my = m(st, p[i]);
            v.push_back(st.x + my * (0 - st.y));
        }
    }
    int sz = v.size();
    if (n - sz > kk) return -1;
    sort(v.begin(), v.end());
    db res = infdb;
    int len = min(n - kk, sz);
    for (int i = 0; i <= v.size()-len; ++i) {
        res = min(res, v[i + len - 1] - v[i]);
    }
    return res;
}
int main () {
    st.x = read(), st.y = read();
    n = read(), kk = read();
    for (int i = 1; i <= n; ++i) {
        p[i].x = read();
        p[i].y = read();
    }
    db ans, tmp1 = solve1(), tmp2 = solve2();
    if (tmp1 == -1) {
        prf(tmp2);
    }
    else if (tmp2 == -1)
        prf(tmp1);
    else
        prf(min(tmp1, tmp2));
    return 0;
}
View Code

D.hanayo和米饭

签到

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <stack>

using namespace std;
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scl(a) scanf("%lld",&a)
#define scll(a,b) scanf("%lld%lld",&a,&b)
#define prl(a) printf("%lld\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",a)
#define ptd(a) printf("%d ",a)
#define scf(a) scanf("%lf",&a)
#define scff(a,b) scanf("%lf%lf",&a,&b)
#define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
#define rint register int
#define mem(a) memset(a,0,sizeof(a))
#define rush() int T;scd(T);while(T--)
#define lc(i) (i<<1)
#define rc(i) (i<<1|1)
#define mp make_pair
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef double db;
inline int read() {char c=getchar();int x=0,f=1;while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}return x*f;}
const int inf = 2147483647-1;
const int maxn = 1e5 + 10;
const ll mod = 1e9 + 7;
int vis[maxn];
int main ()
{    
    int n = read();
    for (int i = 1; i < n; ++i) {
        int x = read();
        vis[x] = 1;
    }
    for (int i = 1; i <= n; ++i) if (!vis[i]) {
        prd(i);
    }
    return 0;
}
View Code

E.rin和快速迭代

边看题边打,就没了

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <stack>

using namespace std;
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scl(a) scanf("%lld",&a)
#define scll(a,b) scanf("%lld%lld",&a,&b)
#define prl(a) printf("%lld\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",a)
#define ptd(a) printf("%d ",a)
#define scf(a) scanf("%lf",&a)
#define scff(a,b) scanf("%lf%lf",&a,&b)
#define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
#define rint register int
#define mem(a) memset(a,0,sizeof(a))
#define rush() int T;scd(T);while(T--)
#define lc(i) (i<<1)
#define rc(i) (i<<1|1)
#define mp make_pair
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef double db;
inline int read() {
    char c=getchar();
    int x=0,f=1;
    while(c<'0'||c>'9') {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
const int inf = 2147483647-1;
const int maxn = 1e5 + 10;
const ll mod = 1e9 + 7;
ll Solve(ll n) {
    ll cnt = 0;
    set<ll> s1,s2;
    ll x = n;
    for(ll i=1; i*i<=n; i++) {
        if(n%i==0) {
            cnt++;
            s1.insert(i);
        }
    }
    for (set<ll>::iterator it = s1.begin(); it != s1.end(); ++it) {
        s2.insert(*it);
        s2.insert(x/(*it));
    }
    return s2.size();
}
ll solve(ll x) {
    ll cnt = 0, tmp = x;
    do {
        tmp = Solve(tmp);
        cnt++;
    } while (tmp != 2);
    return cnt;
}
int main () {
    ll n;
    scl(n);
    prl(solve(n));
    return 0;
}
View Code

F.maki和tree

树形DP,比赛的时候用了假的一遍DFS树形DP骗过去了300ms+,看同校的三遍DFS正解只用了40ms+.看了一下之后别人的代码之后发现,估计是白色块重复统计次数太多,可以用个类似并查集的方式优化

题意:一个树上有黑白两种颜色,问只经过一个黑色点的简单路径有几种。

思路:满足题意的简单路径显然只有白黑白或者是黑白两种,联想了一下一道黑白棋的题,以黑点为根节点深搜的时候注意把某一个新的子树不经过黑点的白色节点数统计为son[v],对白黑白的贡献为son[u] * son[v] 对黑白的贡献为 son[v]

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <stack>

using namespace std;
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scl(a) scanf("%lld",&a)
#define scll(a,b) scanf("%lld%lld",&a,&b)
#define prl(a) printf("%lld\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",a)
#define ptd(a) printf("%d ",a)
#define scf(a) scanf("%lf",&a)
#define scff(a,b) scanf("%lf%lf",&a,&b)
#define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
#define rint register int
#define mem(a) memset(a,0,sizeof(a))
#define rush() int T;scd(T);while(T--)
#define lc(i) (i<<1)
#define rc(i) (i<<1|1)
#define mp make_pair
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef double db;
inline int read() {
    char c=getchar();
    int x=0,f=1;
    while(c<'0'||c>'9') {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
const int inf = 2147483647-1;
const int maxn = 1e5 + 10;
const ll mod = 1e9 + 7;
int n;
struct enode {
    int v, nxt;
}edge[maxn * 2];
int head[maxn], tot;
void add(int u, int v) {
    edge[++tot].v = v;
    edge[tot].nxt = head[u];
    head[u] = tot;
}
char s[maxn];
ll ans = 0;
int son[maxn];
void dfs(int u,int fr) {
    son[u] = 0;
    if (s[u]=='W')son[u] = 1;
    for (int i = head[u]; i; i = edge[i].nxt) {
        int v = edge[i].v;
        if (s[v] == 'B'||v==fr) continue;
        dfs(v,u);
        if (s[u] == 'B') {
            ans += son[v] * son[u];
            ans += son[v];
        }
        son[u] += son[v];
    }
}
int main () {
    n = read();
    scanf("%s",s+1);
    for (int i = 1; i < n; ++i) {
        int u = read(), v = read();
        add(u,v);
        add(v,u);
    }
    for (int i = 1; i <= n; ++i) {
        if (s[i] == 'B') {
            dfs(i,-1);
        }
    }
    prl(ans);
    return 0;
}
View Code

顺便偷偷贴一下三遍DFS

#include <stdio.h>
typedef long long ll;
const int N = 1e5+10;
int head[N] = {0}, nt[N*2], to[N*2], tot = 0;
int down[N] = {0}, up[N] = {0};
ll res = 0;
void add(int x, int y) {
    ++tot;
    to[tot]=y;
    nt[tot]=head[x];
    head[x]=tot;
    ++tot;
    to[tot]=x;
    nt[tot]=head[y];
    head[y]=tot;
}
char s[N];
void dfs_down(int now, int pre) {
    for(int i = head[now]; i; i = nt[i]) {
        if(to[i]==pre) continue;
        dfs_down(to[i], now);
        if(s[to[i]]=='W') down[now] += 1 + down[to[i]];
    }
}
void dfs_up(int now, int pre) {
    for(int i = head[now]; i; i = nt[i]) {
        if(to[i]==pre) continue;
        if(s[now]=='W') {
            up[to[i]] = 1 + up[now] + down[now];
            if(s[to[i]]=='W') up[to[i]] -= 1 + down[to[i]];
        }
        dfs_up(to[i], now);
    }
}
void dfs(int now, int pre) {
    if(s[now]=='B') {
        res += up[now] + down[now];
        res += 1ll * up[now] * down[now];
    }
    ll tmp = 0;
    for(int i = head[now]; i; i = nt[i]) {
        if(to[i]==pre) continue;
        if(s[now]=='B') {
            if(s[to[i]]=='W') {
                tmp += 1ll * (down[to[i]] + 1) * (down[now] - down[to[i]] - 1);
            }
        }
        dfs(to[i], now);
    }
    res += tmp / 2;
}
int main() {
    int n, x, y;
    scanf("%d %s", &n, s+1);
    for(int i = 1; i < n; i++) {
        scanf("%d %d", &x, &y);
        add(x, y);
    }
    dfs_down(1, 0);
    dfs_up(1, 0);
    dfs(1, 0);

    printf("%lld\n", res);
}
View Code

G.eli和字符串

题意:给个字符串,问至少包含任意某个字符K次的最短长度

思路:做一个26*n的数组维护某个字符的前缀和,二分长度,查看是否满足题意

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <stack>

using namespace std;
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scl(a) scanf("%lld",&a)
#define scll(a,b) scanf("%lld%lld",&a,&b)
#define prl(a) printf("%lld\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",a)
#define ptd(a) printf("%d ",a)
#define scf(a) scanf("%lf",&a)
#define scff(a,b) scanf("%lf%lf",&a,&b)
#define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
#define rint register int
#define mem(a) memset(a,0,sizeof(a))
#define rush() int T;scd(T);while(T--)
#define lc(i) (i<<1)
#define rc(i) (i<<1|1)
#define mp make_pair
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef double db;
inline int read() {
    char c=getchar();
    int x=0,f=1;
    while(c<'0'||c>'9') {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
const int inf = 2147483647-1;
const int maxn = 2e5 + 10;
const ll mod = 1e9 + 7;
int sum[30][maxn];
char s[maxn];
int n, k;
bool check(int len) {
    for (int i = 1; i <= n-len+1; ++i) {
        for (int j = 0; j < 30; ++j) {
            if (sum[j][i+len-1]-sum[j][i-1] >= k) return true;
        }
    }
    return false;
}
int main () {
    n = read(), k = read();
    bool flag = false;
    int ans = maxn;
    scanf("%s",s+1);
    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j < 26; ++j) {
            sum[j][i] = sum[j][i-1] + (s[i]==('a'+j)?1:0);
        }
    }
    int l = 1, r = n;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (check(mid)) {
            flag = true;
            r = mid - 1;
            ans = mid;
        } else {
            l = mid + 1;
        }
    }
    if (flag) {
        prd(ans);
    } else puts("-1");
    return 0;
}
View Code

H.nozomi和字符串

跟上面的G题差不多字符变成01,最小值变成最大值

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <stack>

using namespace std;
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scl(a) scanf("%lld",&a)
#define scll(a,b) scanf("%lld%lld",&a,&b)
#define prl(a) printf("%lld\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",a)
#define ptd(a) printf("%d ",a)
#define scf(a) scanf("%lf",&a)
#define scff(a,b) scanf("%lf%lf",&a,&b)
#define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
#define rint register int
#define mem(a) memset(a,0,sizeof(a))
#define rush() int T;scd(T);while(T--)
#define lc(i) (i<<1)
#define rc(i) (i<<1|1)
#define mp make_pair
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef double db;
inline int read() {
    char c=getchar();
    int x=0,f=1;
    while(c<'0'||c>'9') {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
const int inf = 2147483647-1;
const int maxn = 2e5 + 10;
const ll mod = 1e9 + 7;
int sum[30][maxn];
char s[maxn];
int n, k;
bool check(int len) {
    for (int i = 1; i <= n-len+1; ++i) {
        for (int j = 0; j < 30; ++j) {
            if (sum[j][i+len-1]-sum[j][i-1] >= k) return true;
        }
    }
    return false;
}
int main () {
    n = read(), k = read();
    bool flag = false;
    int ans = maxn;
    scanf("%s",s+1);
    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j < 26; ++j) {
            sum[j][i] = sum[j][i-1] + (s[i]==('a'+j)?1:0);
        }
    }
    int l = 1, r = n;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (check(mid)) {
            flag = true;
            r = mid - 1;
            ans = mid;
        } else {
            l = mid + 1;
        }
    }
    if (flag) {
        prd(ans);
    } else puts("-1");
    return 0;
}
View Code

I.nico和niconiconi

线性的dp,我先分了个类,第三种情况是包含了第二种的多判断一下

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <set>
#include <map>
#include <stack>
 
using namespace std;
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scl(a) scanf("%lld",&a)
#define scll(a,b) scanf("%lld%lld",&a,&b)
#define prl(a) printf("%lld\n",a)
#define prd(a) printf("%d\n",a)
#define prf(a) printf("%lf\n",a)
#define ptd(a) printf("%d ",a)
#define scf(a) scanf("%lf",&a)
#define scff(a,b) scanf("%lf%lf",&a,&b)
#define scfff(a,b,c) scanf("%lf%lf%lf",&a,&b,&c)
#define rint register int
#define mem(a) memset(a,0,sizeof(a))
#define rush() int T;scd(T);while(T--)
#define lc(i) (i<<1)
#define rc(i) (i<<1|1)
#define mp make_pair
#define lowbit(x) (x&(-x))
typedef long long ll;
typedef double db;
inline int read() {
    char c=getchar();
    int x=0,f=1;
    while(c<'0'||c>'9') {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
const int inf = 2147483647-1;
const int maxn = 3e5 + 30;
const ll mod = 1e9 + 7;
char s[maxn];
int flag[maxn];
ll dp[maxn];
int main () {
    int n = read(), a = read(), b = read(), c = read();
    scanf("%s",s+1);
    for (int i = 1; i <= n; ++i) {
        if (s[i]=='o'&&s[i-1]=='c'&&s[i-2]=='i'&&s[i-3]=='n') {
            flag[i] = max(1,flag[i]);
            if (s[i+1]=='n'&&s[i+2]=='i') {
                flag[i+2] = max(2,flag[i+2]);
                if (s[i+3]=='c'&&s[i+4]=='o'&&s[i+5]=='n'&&s[i+6]=='i') {
                    flag[i+6] = max(3,flag[i+6]);
                }
            }
        }
        if (flag[i] == 1) i += 3;
    }
    for (int i = 1; i <= n; ++i) {
        dp[i] = dp[i-1];
        if (flag[i] == 1) {
            dp[i] = max(dp[i], dp[i-4] + a);
        } else if (flag[i] == 2) {
            dp[i] = max(dp[i], dp[i-6] + b);
        } else if (flag[i] == 3) {
            dp[i] = max(dp[i], dp[i-10] + c);
            dp[i] = max(dp[i], dp[i-6] + b);
        }
    }
    prl(dp[n]);
    return 0;
}
View Code

J.u's的影响力

公式易推,但是对我这种准备当树论选手的人来说,显然不可,就指望着能靠队友了。

什么指数的扩展欧拉,简直魔幻,矩阵快速幂的+1居然这么用的

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const long long mod = 1e9 +7;
const long long newmod = 1e9 +6;
struct mat
{
    ll a[3][3];
};
mat mat_mul(mat x,mat y)
{
    mat res;
    memset(res.a,0,sizeof(res.a));
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
        for(int k=0;k<3;k++)
        res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j]) % newmod;
    return res;
}
long long mat_pow(long long n)
{
    mat c,res;
    c.a[0][0]=c.a[0][1]=c.a[1][0]=1;
    c.a[1][1]=0;
    memset(res.a,0,sizeof(res.a));
    for(int i=0;i<3;i++)
        res.a[i][i]=1;
    while(n)
    {
        if(n&1) res=mat_mul(res,c);
        c=mat_mul(c,c);
        n=n>>1;
    }
    return res.a[0][1]% newmod;
}
struct matt
{
    ll a[3][3];
};
matt matt_mul(matt x,matt y)
{
    matt res;
    memset(res.a,0,sizeof(res.a));
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
        for(int k=0;k<3;k++)
        res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j]) % newmod;
    return res;
}
long long matt_pow(long long n)
{
    matt c,res;
    c.a[0][0] = c.a[0][1] = c.a[0][2] = c.a[1][0] = c.a[2][2] = 1;
    c.a[1][1] = c.a[1][2] = c.a[2][1] = c.a[2][0] = 0;
    memset(res.a,0,sizeof(res.a));
    for(int i=0;i<3;i++)
        res.a[i][i]=1;
    while(n)
    {
        if(n&1) res=matt_mul(res,c);
        c=matt_mul(c,c);
        n=n/2;
    }
    return res.a[0][1]% newmod;
}
long long qpow(long long a, long long b)
{
    long long res = 1;
    while(b)
    {
        if(b & 1)
        {
            res *= a;
            res %= mod;
        }
        a*= a;
        a %= mod;
        b /= 2;
    }
    return res;
}
int main()
{
    long long n,x,y, a, b;
    cin >> n >>x >> y >> a >> b;
    if(n == 1)
    {
        cout << x % mod << endl;
        return 0;
    }
    if(n == 2)
    {
        cout << y % mod << endl;
        return 0;
    }
    if(a % 1000000007 == 0)
       {
           cout  << 0 << endl;
           return 0;
       }
    x %= mod;
    y %= mod;
    a = qpow(a % mod, b);
    b =  (matt_pow(n) - 1) % newmod + newmod;
 
   // cout << b << endl;
   //23 2 3 2000000014 2
    long long ttt = mat_pow(n - 1) % newmod + newmod;
    long long tt = mat_pow(n - 2) % newmod + newmod;
    //cout << tt<<" " << ttt << endl;
    long long ans = (((qpow(x, tt) % mod) * (qpow(y, ttt) % mod)) % mod * qpow(a, b)) % mod;
    cout << ans % mod<< endl;
 
    return 0;
}
View Code
posted @ 2020-02-05 14:22  czwccc  阅读(122)  评论(0编辑  收藏  举报