1. 程式人生 > 其它 >2022.4.17 省選vp記

2022.4.17 省選vp記

前言

去年沒有打 NOIP,所以今年自然沒法打省選,就 vp 一下了。

Day 1

T1 前處理器

本題思路:
Hash+字串+模擬
除了程式碼有些長,然後樣例比較迷惑之後
這道題就是細節。難度好像不大
我第一遍的時候被 空串 給卡掉了。這是第二遍程式碼:

#include<bits/stdc++.h>
#define int long long
#define rint register int
#define ull unsigned long long
#define pii pair<int,int> 
#define fir first
#define sec second
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define Down(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
using PII = pair<int,int>;
typedef long long ll;
const int N=110;
const int Mod=19260817;
const ull Bas=13331;
int n,dcnt;
struct Hash_Table{
    struct edge{int pre,nxt,val;ull to;}e[N*N];
    int head[Mod],ecnt;
    void insert(ull x,int id){
        e[++ecnt]={0,head[x%Mod],id,x},e[head[x%Mod]].pre=ecnt,head[x%Mod]=ecnt;
    }
    void erase(ull x){
        for(rint i=head[x%Mod];i;i=e[i].nxt){
            if(e[i].to==x){
                int pr=e[i].pre,nx=e[i].nxt;
                if(pr) e[pr].nxt=nx;
                e[nx].pre=pr,e[i].to=e[i].val=e[i].pre=e[i].nxt=0;       
                return ;
            }
        }
    }
    int query(ull x){
        for(rint i=head[x%Mod];i;i=e[i].nxt){
            if(e[i].to==x) return e[i].val;
        } return -1;
    }
}mp;
template<typename T>inline void ckmax(T &x,T y){x=x>y?x:y;}
template<typename T>inline void ckmin(T &x,T y){x=x<y?x:y;}
string val[N];bool vis[N];
namespace IO{
    ull get_hs(string s){
        ull res=0;
        for(int i=0;i<s.length();++i) res=res*Bas+s[i];
        return res;
    }
    bool imp(char x){
        if(isalpha(x)) return 1;
        if(isdigit(x)) return 1;
        return x=='_';
    }
    void solve(string s){
        int len=s.length();
        for(int i=0;i<len;++i){
            int j=i; string tmp;
            while(j<len&&imp(s[j])) tmp+=s[j++];
            ull cur=get_hs(tmp),id=mp.query(cur);
            if(id!=-1&&!vis[id]){
                vis[id]=1;
                solve(val[id]);
                vis[id]=0;
            }else{
                cout<<tmp;
            }
            if(j<len) putchar(s[j]);
            i=j;
        }
        return ;
    }
}
using namespace IO;
namespace Fast{
	inline int read(){
        int t=0;
        char c=getchar();
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') t=10*t+(c^48),c=getchar();
        return t;
    }
    inline void write(int x){
        if(x<10){
            putchar(x|48);
            return;
        }
        write(x/10);
        putchar((x%10)|48);
}}
using namespace Fast;
signed main(void){
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    n=read();
    while(n--){
        string str; getline(cin,str);
        int len=str.length();
        if(str[0]=='#'){
            if(str[1]=='d'){
                string s1;
                int pter=8;
                while(str[pter]!=' ') s1+=str[pter++];
                mp.insert(get_hs(s1),++dcnt);
                ++pter;
                for(int j=pter;j<len;++j) val[dcnt]+=str[j];
            }else{
                string s;
                for(int j=7;j<len;++j) s+=str[j];
                ull cur=get_hs(s);
                mp.erase(cur);
            }
            puts("");
        }else{
            solve(str);
            putchar('\n');   
        }
    }
    return 0;    
	//fclose(stdin);
	//fclose(stdout);
}

T2 填樹

沒有什麼好的思路
目前已知最優解是那個 樹形DP+數學,顯然我不會。。。。
所以只能暴搜了

#include<iostream>
#include<iomanip>
#include<queue>
#include<stack>
#include<set>
#include<algorithm>
#include<bitset>
#include<string>
#include<vector>
#include<iosfwd>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#define rint register int
using namespace std;
using PII = pair<int,int>;
#define ll long long
#define inf 4557430888798830399
using namespace std;
namespace Fast{
	inline int read(){
        int t=0;
        char c=getchar();
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') t=10*t+(c^48),c=getchar();
        return t;
    }
    inline void write(int x){
        if(x<10){
            putchar(x|48);
            return;
        }
        write(x/10);
        putchar((x%10)|48);
}}
using namespace Fast;
const ll mod=1000000007,inf = 0x3f3f3f3f3f,N=210,M=N*2;
ll n,k,l[N],r[N],h[N],e[M],ne[M],idx,f[N][50][50],g[N][50][50];
ll qmi(ll a,ll b,ll p){
	ll res=1;
	while(b){
		if(b&1) res=res*a%p;
		a=a*a%p;
		b>>=1;
	}
	return res;
}
void adds(ll a,ll b){
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(ll u,ll fa){
	for(ll i=h[u];~i;i=ne[i]){
		ll v=e[i];
		if(v==fa) continue;
		for(ll j=1;j<=500;j++){
			for(ll k1=j;k1<=min(500ll,k1+k);k1++){
				for(ll p=l[v];p<=r[v];p++){
					ll t1=min(j,p),t2=max(k1,p);
					f[v][t1][t2]=(f[v][t1][t2]+f[u][j][k1])%mod;
				}
			}
		}
		for(ll j=1;j<=500;j++){
			for(ll k1=j;k1<=min(500ll,k1+k);k1++){
				for(ll p=l[v];p<=r[v];p++){
					ll t1=min(j,p),t2=max(k1,p);
					g[v][t1][t2]=((g[v][t1][t2]+g[u][j][k1])%mod+f[u][j][k1]*p%mod)%mod;
				}
			}
		}
		dfs(v,u);
	}
}
int main(){
	memset(h,-1,sizeof h);
	n=read(),k=read();
	for(ll i=1;i<=n;i++){
		scanf("%lld%lld",&l[i],&r[i]);
	}
	for(ll i=1;i<n;i++){
		ll x,y;
		scanf("%lld%lld",&x,&y);
		adds(x,y),adds(y,x);
	}
	ll cnt=0,sum=0;
	ll a1=0,b1=0;
	for(ll root=1;root<=n;root++){
		ll cnt1=0,cnt2=0,sum1=0,sum2=0;
		memset(f,0,sizeof f);
		memset(g,0,sizeof g);
		cnt2+=r[root]-l[root]+1;
		for(ll i=l[root];i<=r[root];i++){
			f[root][i][i]=1;
			g[root][i][i]=i;
			sum2=(sum2+i)%mod;
		}
		dfs(root,-1);
		for(ll i=1;i<=n;i++){
			for(ll j=1;j<=500;j++){
				for(ll p=j;p<=min(500ll,j+k);p++){
					cnt1=(cnt1+f[i][j][p])%mod,sum1=(sum1+g[i][j][p])%mod;
				}
			}
		}
		cnt1=(cnt1-cnt2+mod)%mod;
		sum1=(sum1-sum2+mod)%mod;
		a1=(a1+cnt1)%mod;
		b1=(b1+sum1)%mod;
		cnt=(cnt+cnt2)%mod;
		sum=(sum+sum2)%mod;
	}
	ll iv2=qmi(2,mod-2,mod);
	cnt=(cnt+a1*iv2%mod)%mod;
	sum=(sum+b1*iv2%mod)%mod;
	printf("%lld\n",cnt);
	printf("%lld",sum);
	return 0;
}

T3 學術社群

一個網路流題,但是我現在寫個網路流模板都還費勁兒,這個題自然就不會了
暴力也只會打一個數據點的。

#include<iostream>
#include<iomanip>
#include<queue>
#include<stack>
#include<set>
#include<algorithm>
#include<bitset>
#include<string>
#include<vector>
#include<iosfwd>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#define int long long
#define rint register int
using namespace std;
using PII = pair<int,int>;
typedef long long ll;
using namespace std;
#define pb push_back
const int N=8e4,M=3e5+5;
int n,m,cnt=0;
string nam[N],s[M][4];
map <string, int> mp;
vector <int> ls[N];vector <int> lx[N];
vector <int> id[N];vector <int> ans;
bool vis[M];
int main()
{
	int T; read(T);
	while(T--){
		cin>>n>>m; 
		mp.clear();
		for(int i=1;i<=n;i++)
			cin>>nam[i],mp[nam[i]] = i, ls[i].clear(), lx[i].clear(), id[i].clear();
		queue <int> que;
		memset(vis, 0, sizeof(vis));
		for(int i = 1; i <= m; i++){
			cin>>s[i][1]>>s[i][2] >> s[i][3];
			if(s[i][3]=="loushang" && mp.find(s[i][2]) != mp.end()) ls[mp[s[i][2]]].pb(i);
			else if(s[i][3] == "louxia" && mp.find(s[i][2]) != mp.end()) lx[mp[s[i][2]]].pb(i);
			else que.push(i), vis[i] = 1;
			id[mp[s[i][1]]].pb(i);
		}
		cnt = 0; ans.clear();
		while(!que.empty()){
			int k = que.front(); que.pop();
			int u = mp[s[k][1]];
			bool flag = 0;
			ans.pb(k);
			for(auto it : lx[u]){
				if(vis[it]) 
				    continue;
				vis[it] = 1;que.push(it);
				flag = 1;cnt++;
				break;
			}
			if(flag) 
			    continue;
			for(auto it : ls[u]){
				if(vis[it]) 
				    continue;
				vis[it]=1,que.push(it);
				cnt++;
				break;
			}
		}
		cout<<cnt<<endl;
		for(auto it : ans) 
		    cout<<it<<endl;
		for(int i = 1; i <= m; i++) 
		    if(!vis[i]) 
			    cout<<i<<" ";
		putchar('\n');
		void();	
	} 
	return 0;
}