暑假集训8

A. T1 出了个大阴间题

40分的dfs:

#include <bits/stdc++.h>
  
using namespace std;
  
typedef long long ll;
const int maxn = 25;
const ll mod = 1e9 + 7;

int n, b[maxn], c[maxn];
ll ans, Maxa, k;
bool v[maxn];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

void check()
{
    ll nowa = c[b[1]], nowb = 0, nowans = 0;
    for(int i=2; i<=n; i++)
    {
        if(nowa != c[b[i]])
        {
            nowa = max(nowa, (ll)c[b[i]]);
        }
        else nowa++;
        nowans = (nowans+k*nowa%mod+nowb)%mod;
        nowb = (nowb<<1)+1;
    }
    //printf("nowa = %lld\n", nowa);
    //printf("nowans = %lld\n\n", nowans);
    if(nowa > Maxa) 
    {
        ans = nowans; Maxa = nowa;
    }
    else if(nowa == Maxa)
    {
        ans = (ans + nowans) % mod;
    }
    return;
}

void dfs(int a, int n)
{
    if(a > n)
    {
        check();
        return;
    }
    for(int i=1; i<=n; i++) 
    {
        if(v[i]) continue;
        v[i] = 1;
        b[a] = i;
        dfs(a+1, n);
        v[i] = 0;
    }
}

int main()
{
    freopen("repair.in", "r", stdin);
    freopen("repair.out", "w", stdout);
    
    n = read(); k = read();
    for(int i=1; i<=n; i++)
    {
        c[i] = read();
    }
    dfs(1, n);
    printf("%lld %lld\n", Maxa, ans);
  
    return 0;
}
View Code

鹤个题解:(不知道用哪个he就选个好看的)

f[i]表示当前状态,f[i].first是maxa,f[i].second是maxa确定的所有方案的代价总和,g[i]记录从g[1]到g[i-1]累加的maxa特定的所有方案数,num用来记录b的个数,可以从二进制下任意去掉一个1的状态转移,b预处理b的值[我在写dfs时就发现了b的影响只和个数有关的事,但是由于没有想到状压,也没有用到]。

map似乎是个好东西可以把maxval和答案存到一起。

#include <bits/stdc++.h>
  
using namespace std;
  
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 6e5 + 21;
const ll mod = 1e9 + 7;

int m, n, U, maxval, val[25], b[25];
ll num[1<<18];
map<int, ll> f[1<<18], g[1<<18];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

int main()
{
    freopen("repair.in", "r", stdin);
    freopen("repair.out", "w", stdout);
    
    n = read(); m =read(); U = (1<<n)-1;
    for(int i=1; i<=n; i++) val[i] = read();
    for(int i=2; i<=n; i++) b[i] = b[i-1]<<1|1;
    for(int i=1; i<=n; i++) 
    {
        f[1<<(i-1)][val[i]] = 0; g[1<<(i-1)][val[i]]++;
    }
    for(int i=1; i<U; i++)
    {
        num[i] = num[i&(i-1)]+1;
        for(int j=1,k; j<=n; j++)
        {
            if((i>>(j-1))&1) continue;
            k = i|(1<<(j-1));
            for(auto c : f[i])
            {
                ll to = (c.first==val[j]?val[j]+1:max(c.first, val[j]));
                f[k][to] = (f[k][to]+f[i][c.first]+(to*m%mod+b[num[i]])%mod*g[i][c.first]%mod)%mod;
                g[k][to] = (g[k][to]+g[i][c.first])%mod;
            }
        }
    }
    for(auto i : f[U]) maxval = max(maxval, i.first);
    printf("%d %lld", maxval, f[U][maxval]%mod);
  
    return 0;
}
View Code

 

B. T2 最简单辣快来做

我盯着这个编号为奇数的测试点保证a,b与M互质看了好半天想不出来如果不互质会怎样,到最后也没看明白,好像暴力和正解都和它无关……

正解有一些神奇的预处理:

1.光速幂,其实就是一种分块,ra存整的,bsa存余数,然后就可以搭配了。

2.不需要每次查询都算一遍答案,用0123记录一下以每一个点为通信中心时的各个方向的区域的总贡献,查询时只要找到查询点和它旁边离它最近(周围就行)的点,直接用统计好的贡献加上有了查询点之后偏移造成的新贡献就好了。统计贡献时的循环其实就是前缀和的套路。

#include <bits/stdc++.h>
  
using namespace std;
  
typedef long long ll;
typedef unsigned long long ull;
const int block = 50000, maxn = 2004;
int n, q; ll mod, a, b;
int x[maxn], y[maxn], fx[maxn], fy[maxn], h[maxn];
ll ra[block+100], rb[block+100], bsa[block+100], bsb[block+100];
ll sum[maxn][maxn][4];

inline ll read()
{
    ll x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline ll powa(ll zhi) {return ra[zhi/block]*bsa[zhi%block]%mod; }
inline ll powb(ll zhi) {return rb[zhi/block]*bsb[zhi%block]%mod; }

inline void Prework()
{
    bsa[0] = bsb[0] = ra[0] = rb[0] = 1;
    for(int i=1; i<=block; i++) 
    {
        bsa[i] = bsa[i-1]*a%mod; bsb[i] = bsb[i-1]*b%mod;
    }
    for(int i=1; i<=block; i++)
    {
        ra[i] = ra[i-1]*bsa[block]%mod; rb[i] = rb[i-1]*bsb[block]%mod;
    }
    sort(fx+1, fx+1+n); sort(fy+1, fy+1+n);
    for(int i=1; i<=n; i++)
    {
        x[i] = lower_bound(fx+1, fx+1+n, x[i])-fx; y[i] = lower_bound(fy+1, fy+1+n, y[i])-fy;
        sum[x[i]][y[i]][0] = sum[x[i]][y[i]][1] = sum[x[i]][y[i]][2] = sum[x[i]][y[i]][3] = h[i];
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            sum[i][j][0] = (sum[i][j][0]+sum[i][j-1][0]*powb(fy[j]-fy[j-1])%mod)%mod;
        }
        for(int j=1; j<=n; j++)
        {
            sum[i][j][0] = (sum[i][j][0]+sum[i-1][j][0]*powa(fx[i]-fx[i-1])%mod)%mod;
        }
        for(int j=n; j>=1; j--)
        {
            sum[i][j][1] = (sum[i][j][1]+sum[i][j+1][1]*powb(fy[j+1]-fy[j])%mod)%mod;
        }
        for(int j=n; j>=1; j--)
        {
            sum[i][j][1] = (sum[i][j][1]+sum[i-1][j][1]*powa(fx[i]-fx[i-1])%mod)%mod;
        }
    }
    for(int i=n; i>=1; i--)
    {
        for(int j=1; j<=n; j++)
        {
            sum[i][j][2] = (sum[i][j][2]+sum[i][j-1][2]*powb(fy[j]-fy[j-1])%mod)%mod;
        }
        for(int j=1; j<=n; j++)
        {
            sum[i][j][2] = (sum[i][j][2]+sum[i+1][j][2]*powa(fx[i+1]-fx[i])%mod)%mod;
        }
        for(int j=n; j>=1; j--)
        {
            sum[i][j][3] = (sum[i][j][3]+sum[i][j+1][3]*powb(fy[j+1]-fy[j])%mod)%mod;
        }
        for(int j=n; j>=1; j--)
        {
            sum[i][j][3] = (sum[i][j][3]+sum[i+1][j][3]*powa(fx[i+1]-fx[i])%mod)%mod;
        }
    }
}

inline ll Work(int px, int py)
{
    int dx = upper_bound(fx+1, fx+1+n, px)-fx;
    int dy = upper_bound(fy+1, fy+1+n, py)-fy;
    ll res = 0;
    if(dx-1 && dy-1)
    {
        res = (res+sum[dx-1][dy-1][0]*powa(px-fx[dx-1])%mod*powb(py-fy[dy-1])%mod)%mod;
    }
    if(dx-1 && dy<=n)
    {
        res = (res+sum[dx-1][dy][1]*powa(px-fx[dx-1])%mod*powb(fy[dy]-py)%mod)%mod;
    }
    if(dx<=n && dy-1)
    {
        res = (res+sum[dx][dy-1][2]*powa(fx[dx]-px)%mod*powb(py-fy[dy-1])%mod)%mod;
    }
    if(dx<=n && dy<=n)
    {
        res = (res+sum[dx][dy][3]*powa(fx[dx]-px)%mod*powb(fy[dy]-py)%mod)%mod;
    }

    return res;
}

int main()
{
    freopen("satellite.in", "r", stdin);
    freopen("satellite.out", "w", stdout);
    
    n = read(); q = read(); read(); read();
    mod = read(); a = read(); b = read();
    for(int i=1; i<=n; i++)
    {
        h[i] = read(); x[i] = fx[i] = read(); y[i] = fy[i] = read();
    }
    Prework();
    for(int i=1; i<=q; i++)
    {
        int per = read(), qer = read();
        printf("%lld\n", Work(per, qer));
    }
  
    return 0;
}
View Code

 

C. T3 是我的你不要抢

第一印象:这不就是AC自动机专题里的 玄武密码 吗?于是经过string优化空间和离线问题之类的一顿改编然后发现样例都过不了,才发现没看到只能用后缀……

一顿魔改,小样例终于过了但是大样例就是不对,到最后交了一个错的+特判,然后特判有分。

对着caorong的改了一下午KMP,T了个71:

#include <bits/stdc++.h>
  
using namespace std;
  
typedef long long ll;
const int maxn = 1e6 + 2;
const int N = 6e5 + 2;
const ll mod = 1e9 + 7;
const int inf = (1<<29);

int n, Q, nxt[N], f[N], len1, len2, ans[maxn];
vector<string> t;
string s;

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

struct node 
{
    int x, y, id;
    bool operator < (const node &T) const 
    {
        if(y == T.y) return x < T.x;
        return y < T.y;
    }
}q[maxn];

int main()
{
    freopen("string.in", "r", stdin);
    freopen("string.out", "w", stdout);
    
    n = read(); Q = read();
    for(register int i=1; i<=n; i++)
    {
        cin >> s; s = '0'+s;
        t.push_back(s);
    }
    for(register int i=1; i<=Q; i++)
    {
        q[i].x = read()-1; q[i].y = read()-1; q[i].id = i;
    }
    sort(q+1, q+1+Q);
    for(register int i=1; i<=Q; )
    {
        int l = i, r = i; while(q[r+1].y == q[l].y && r+1<=Q) r++;
        for(register int j=1; j<len1; j++) nxt[j] = 0; 
        int y = q[i].y; len1 = t[y].size();

        //cout << t[y] << endl;
        for(register int o=2,j=0; o<len1; o++)
        {
            while(j > 0 && t[y][o] != t[y][j+1]) j = nxt[j];
            //if(t[y][o] == t[y][j+1]) j++;
            //nxt[o] = j;
            if(t[y][o] == t[y][j+1]) nxt[o] = ++j;
            //printf("nxt[%d] = %d\n", o, nxt[o]);
        }
        //for(int j=1; j<=len2; j++) f[j] = 0;
        for(register int op=l; op<=r; op++)
        {
            if(op > l && q[op].x == q[op-1].x)
            {
                ans[q[op].id] = ans[q[op-1].id]; continue;
            }
            for(register int j=1; j<len2; j++) f[j] = 0;
            int x = q[op].x;
            len2 = t[x].size();

            //cout << t[x] << endl;
            int st = max(1, len2-len1+1);
            for(register int o=1,j=0; o<len2; o++)
            {
                while(j > 0 && t[x][o] != t[y][j+1]) j = nxt[j];
                //if(t[x][o] == t[y][j+1]) j++;
                //f[o] = j;
                if(t[x][o] == t[y][j+1]) f[o] = ++j;
                //printf("f[%d] = %d\n", o, f[o]);
            }
            ans[q[op].id] = f[len2-1];
        }
        for(register int i=1; i<=len2; i++) f[i] = 0;
        i = r+1;
    }
    for(register int i=1; i<=Q; i++) 
    {
        printf("%d\n", ans[i]);
    }
  
    return 0;
}
71

又抄了个hash的A了,然后被同学的鬼畜数据卡成了99:

#include <bits/stdc++.h>
  
using namespace std;
  
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 6e5 + 21;
const ull B = 131;

int n, Q, maxlen, ans, len[maxn];
char s[maxn];
ull po[maxn];
vector<ull> c[maxn], pre[maxn];
unordered_map<int, ull> mp1[maxn];

inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
        {
            f = -1;
        }
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = (x << 1) + (x << 3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline ull getsh(int x, int l, int r)
{
    return pre[x][r]-pre[x][l-1]*po[r-l+1];
}

int main()
{
    freopen("string.in", "r", stdin);
    freopen("string.out", "w", stdout);
    
    n = read(); Q = read();
    for(int i=1; i<=n; i++)
    {
        scanf("%s", s+1); c[i].push_back(0); pre[i].push_back(0);
        len[i] = strlen(s+1); maxlen = max(maxlen, len[i]);
        for(int j=1; j<=len[i]; j++)
        {
            c[i].push_back(s[j]-'a'+1);
            pre[i].push_back(pre[i][j-1]*B+c[i][j]);
        }
    }
    po[0] = 1; for(int i=1; i<=maxlen; i++) po[i] = po[i-1]*B;
    while(Q--)
    {
        int y = read(), x = read(); maxlen = min(len[x], len[y]);
        if(mp1[x].find(y) != mp1[x].end())
        {
            printf("%lld\n", mp1[x][y]); continue;
        }
        for(int i=maxlen; i>=0; i--)
        {
            if(getsh(x, 1, i) == getsh(y, len[y]-i+1, len[y]))
            {
                ans = i; break;
            }
        }
        mp1[x][y] = ans;
        printf("%d\n", ans);
    }
  
    return 0;
}
View Code

 

D. T4 显然也是我整的

当我发现s<=n/2的答案就是把s求个gcd之后,不知道大一点的s怎么办了,本着骗分的思路交了一个gcd,结果(⊙o⊙)…一分都没有,输出1或暴力并查集建图好像都有分的……

以下是正解的代码但不是我写的,CV一下不想改了**

//CV题解很有瘾
#include <bits/stdc++.h>
#define int long long 
#define ull unsigned long long
#define f() cout<<"Failed"<<endl
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
const int N=2e5+10;
int n,m,T,top,sta[N],s[N];
set<int> se;
void work(int &ans,int &n)
{
    int num=(*se.begin()),temp=2*num-n;
    for(auto it=se.begin();it!=se.end();it++) sta[++top]=(*it);
    ans+=temp; n-=temp; se.clear();
    for(int i=1;i<=top;i++) se.insert(sta[i]-temp);
}
int solve(int n)
{
    int ans=top=0,gcd=0;
    if((*se.begin())>n/2) work(ans,n);
    for(auto it=se.begin();it!=se.end();it++)
        if((*it)<=n/2) gcd=__gcd(gcd,(*it));
        else break;
    se.erase(se.begin(),se.upper_bound(n/2));
    for(auto it=se.begin();it!=se.end();it++)
        if((*it)+gcd<=n) gcd=__gcd(gcd,(*it));
        else break;
    se.erase(se.begin(),se.upper_bound(n-gcd));
    if(!se.size()) return ans+gcd;
    int temp=gcd+n%gcd; top=0;
    for(auto it=se.begin();it!=se.end();it++) sta[++top]=(*it);
    se.clear(); for(int i=1;i<=top;i++) se.insert(temp+sta[i]-n); se.insert(gcd);
    return ans+solve(temp);
}
signed main()
{
    freopen("graph.in","r",stdin); freopen("graph.out","w",stdout);
    T=read();
    while(T--)
    {
        n=read(); m=read(); se.clear();
        for(int i=1;i<=m;i++) s[i]=read();
        for(int i=1;i<=m;i++) se.insert(s[i]);
        printf("%lld\n",solve(n));
    }
    return 0;
}
View Code

 

posted @ 2022-08-22 22:31  Catherine_leah  阅读(66)  评论(0编辑  收藏  举报
/* */