2019icpc徐州网络赛
A Who is better?
题意
excrt+斐波那契博弈
分析
Java的BigInteger对象默认为null,不能直接比较。
代码
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
    static int n;
    static BigInteger[] a=new BigInteger[25];
    static BigInteger[] b=new BigInteger[25];
    static BigInteger INF=BigInteger.valueOf((long)1e15);
    static BigInteger[] fib=new BigInteger[110];
    static int cnt=0;
    static void init(){
        fib[1]=BigInteger.ONE;
        fib[2]=BigInteger.ONE;
        cnt=2;
        for(int i=3;i<110;i++){
            fib[i]=fib[i-1].add(fib[i-2]);
            if(fib[i].compareTo(INF)>0){
                break;
            }
            cnt++;
        }
    }
    static boolean check(BigInteger t){
        for(int i=1;i<=cnt;i++){
            if(fib[i]==null){
                return false;
            }
            if(fib[i].compareTo(t)==0){
                return true;
            }
        }
        return false;
    }
    static BigInteger exgcd(BigInteger a,BigInteger b,BigInteger[] x,BigInteger[] y){
        if(a.compareTo(BigInteger.ZERO)==0 && b.compareTo(BigInteger.ZERO)==0){
            return new BigInteger("-1");
        }
        if(b.compareTo(BigInteger.ZERO)==0){
            x[0]= BigInteger.ONE;
            y[0]=BigInteger.ZERO;
            return a;
        }
        BigInteger d=exgcd(b,a.mod(b),y,x);
        y[0]=y[0].subtract(a.divide(b).multiply(x[0]));
        return d;
    }
    static BigInteger excrt(){
        BigInteger[] x=new BigInteger[2];
        BigInteger[] y=new BigInteger[2];
        BigInteger M=b[1];
        BigInteger ans=a[1];
        for(int i=2;i<=n;i++){
            BigInteger ai=M,bi=b[i],ci=(a[i].subtract(ans.mod(bi)).add(bi)).mod(bi);
            BigInteger gcd=exgcd(ai,bi,x,y);
            BigInteger bg=bi.divide(gcd);
            if(ci.mod(gcd).compareTo(BigInteger.ZERO)!=0){
                return new BigInteger("-1");
            }
            x[0]=x[0].multiply(ci.divide(gcd)).mod(bg);
            ans=ans.add(x[0].multiply(M));
            M=M.multiply(bg);
            ans=(ans.mod(M).add(M)).mod(M);
        }
        return (ans.mod(M).add(M)).mod(M);
    }
    public static void main(String[] args) {
        Scanner cin=new Scanner(System.in);
        init();
        n=cin.nextInt();
        for(int i=1;i<=n;i++){
            b[i]=cin.nextBigInteger();
            a[i]=cin.nextBigInteger();
        }
        BigInteger ans=excrt();
        if(ans.compareTo(BigInteger.valueOf(-1))==0){
            System.out.println("Tankernb!");
        }else{
            if(check(ans)){
                System.out.println("Lbnb!");
            }else{
                System.out.println("Zgxnb!");
            }
        }
    }
}
B so easy
题意
两种操作,删除一个数,询问一个数(不一定还在)的后继。
分析
并查集,初始化每个数查询的答案就是本身,删除之后答案就是\(find(x+1)\),要离散化。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=2e6+50;
struct Orz{
    vector<int> a;
    void init(){
        a.clear();
    }
    int siz(){
        return a.size();
    }
    void add(int x){
        a.push_back(x);
    }
    void work(){
        sort(a.begin(),a.end());
        a.erase(unique(a.begin(),a.end()),a.end());
    }
    int idx(int x){
        return lower_bound(a.begin(),a.end(),x)-a.begin()+1;
    }
    int val(int i){
        return a[i-1];
    }
}orz;
int n,q,o[N],a[N],p[N];
int find(int x){
    return x==p[x]?p[x]:p[x]=find(p[x]);
}
int main(){
    scanf("%d%d",&n,&q);
    orz.init();
    for(int i=1;i<=q;i++){
        scanf("%d%d",&o[i],&a[i]);
        orz.add(a[i]);
        orz.add(a[i]+1);
    }
    orz.work();
    int m=orz.siz();
    for(int i=1;i<=m;i++){
        p[i]=i;
    }
    for(int i=1;i<=q;i++){
        int k=orz.idx(a[i]);
        if(o[i]==1){
            if(find(k)==k){
                p[k]=find(k+1);
            }
        }else{
            int v=orz.val(find(k));
            printf("%d\n",v);
        }
    }
    return 0;
}
C Buy Watermelon
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	scanf("%d",&n);
	if(n%2==0 && n!=2)
	puts("YES");
	else puts("NO");
}
D Carneginon
题意
给一个串T和多个串S,根据长度大小和是否为子串判断输出。
分析
题目说明的复杂度刚好就是暴力KMP。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+50;
int n;
char s[N],t[N];
int nex[N];
void getNext(char s[],int n){
    int i=0,j=-1;
    nex[0]=-1;
    while(i<n){
        if(j==-1 || s[i]==s[j]){
            nex[++i]=++j;
        }else{
            j=nex[j];
        }
    }
}
int kmp(char s[],int n,char p[],int m){
    int i=0,j=0;
    getNext(p,m);
    while(i<n && j<m){
        if(j==-1 || s[i]==p[j]){
            i++;
            j++;
        }else{
            j=nex[j];
        }
        if(j==m){
            return i-j+1;
        }
    }
    return -1;
}
int main(){
    scanf("%s",t);
    int tl=strlen(t);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%s",s);
        int sl=strlen(s);
        if(tl>sl){
            int p=kmp(t,tl,s,sl);
            if(p!=-1){
                printf("my child!\n");
            }else{
                printf("oh, child!\n");
            }
        }else if(tl<sl){
            int p=kmp(s,sl,t,tl);
            if(p!=-1){
                printf("my teacher!\n");
            }else{
                printf("senior!\n");
            }
        }else if(tl==sl){
            if(strcmp(t,s)==0){
                printf("jntm!\n");
            }else{
                printf("friend!\n");
            }
        }
    }
    return 0;
}
E XKC's basketball team
题意
对于每个\(a[i]\),查询右边比\(a[i]+m\)大的最远距离。
分析
不用离散化,不用主席树,不用权值线段树。。。
只需要建正常的线段树维护最大值即可,查询时尽量先走右子树。
代码
#include <bits/stdc++.h>
using namespace std;
#define ls i<<1
#define rs i<<1|1
#define mid (l+r)/2
const int N=5e5+50;
int n,m,a[N],ans[N];
int mx[N*4];
void pushup(int i){
    mx[i]=max(mx[ls],mx[rs]);
}
void build(int i,int l,int r){
    mx[i]=0;
    if(l==r){
        return;
    }
    build(ls,l,mid);
    build(rs,mid+1,r);
}
void insert(int i,int l,int r,int p){
    if(l==r && l==p){
        mx[i]=a[p];
        return;
    }
    if(p<=mid){
        insert(ls,l,mid,p);
    }else{
        insert(rs,mid+1,r,p);
    }
    pushup(i);
}
int query(int i,int l,int r,int k){
    if(l==r){
        if(mx[i]>=k){
            return l;
        }else{
            return -1;
        }
    }
    if(mx[rs]>=k){
        return query(rs,mid+1,r,k);
    }else{
        if(mx[ls]>=k){
            return query(ls,l,mid,k);
        }else{
            return -1;
        }
    }
}
void debug(int i,int l,int r){
    printf("%d %d %d\n",l,r,mx[i]);
    if(l==r){
        return;
    }
    debug(ls,l,mid);
    debug(rs,mid+1,r);
}
int main(){
//    freopen("in.txt","r",stdin);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    build(1,1,n);
    for(int i=n;i>=1;i--){
        int t=query(1,1,n,a[i]+m);
        if(t==-1){
            ans[i]=t;
        }else{
            ans[i]=t-i-1;
        }
        insert(1,1,n,i);
//
    }
    for(int i=1;i<=n;i++){
        printf("%d%c",ans[i],i==n?'\n':' ');
    }
    return 0;
}
G Colorful String
题意
定义子串的价值为不同字符个数,求出所有回文子串的价值之和。
分析
回文树模板,插入的时候由另一个回文子串转移而来,判断新加入的字符是否再上一个回文子串中出现,若否,则价值+1。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+50;
struct PT{
    int next[N][26];
    int vis[N][26];
    int val[N];
    int fail[N];
    int cnt[N];
    int num[N];
    int len[N];
    int S[N];
    int last;
    int id[N];
    int n;
    int p;
    int newnode(int l){
        for(int i=0;i<26;i++){
            next[p][i]=0;
        }
        cnt[p]=0;
        num[p]=0;
        len[p]=l;
        return p++;
    }
    void init(){
        p=0;
        newnode(0);
        newnode(-1);
        last=0;
        n=0;
        S[n]=-1;
        fail[0]=1;
    }
    int getFail(int x){
        while(S[n-len[x]-1]!=S[n]){
            x=fail[x];
        }
        return x;
    }
    void add(int c){
        c-='a';
        S[++n]=c;
        int cur=getFail(last);
        if(!next[cur][c]){
            int now=newnode(len[cur]+2);
            for(int i=0;i<26;i++){
                vis[now][i]=vis[cur][i];
            }
            val[now]=val[cur];
            vis[now][c]=1;
            if(!vis[cur][c]){
                val[now]++;
            }
            fail[now]=next[getFail(fail[cur])][c];
            num[now]=num[fail[now]]+1;
            next[cur][c]=now;
        }
        last=next[cur][c];
        cnt[last]++;
        id[last]=n;
    }
    void count(){
        for(int i=p-1;i>=0;i--){
            cnt[fail[i]]+=cnt[i];
        }
    }
    ll solve(){
        ll ans=0;
        for(int i=2;i<p;i++){
            ans+=1ll*val[i]*cnt[i];
        }
        return ans;
    }
}ac;
char s[N];
int main(){
//    freopen("in.txt","r",stdin);
    scanf("%s",&s);
    int len=strlen(s);
    ac.init();
    for(int i=0;i<len;i++){
        ac.add(s[i]);
    }
    ac.count();
    ll ans=ac.solve();
    printf("%lld\n",ans);
}
J Random Access Iterator
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e6+50;
const int mod=1e9+7;
ll dp[MAXN];
vector<int>v[MAXN];
int d[MAXN];
int ans=0;
ll q_pow(ll a,ll k)
{
	ll ans=1;
	while(k)
	{
		if(k&1)
		{
			ans*=a;
			ans%=mod;
		}
		a*=a;
		a%=mod;
		k>>=1;
	}
	return ans;
}
void dfs(int now,int pre,int x)
{
	ans=max(ans,x);
	d[now]=x;
	int l=v[now].size();
	for(int i=0;i<l;i++)
	{
		int to=v[now][i];
		if(to==pre)continue;
		dfs(to,now,x+1);
	}
}
void solve(int now,int pre)
{
	int l=v[now].size();
	if(l==1 && now!=1)
	{
		dp[now]=(d[now]==ans);
		return ;
	}
	ll ans=0;
	for(int i=0;i<l;i++)
	{
		int to=v[now][i];
		if(to==pre)continue;
		solve(to,now);
		ans+=dp[to];
		ans%=mod;
	}
	if(now!=1)l--;
	ans=ans*q_pow(l,mod-2)%mod;
	ans=(1-ans+mod)%mod;
	ans=q_pow(ans,l);
	ans=(1-ans+mod)%mod;
	dp[now]=ans;
}
int main()
{
	ios::sync_with_stdio(false);
	int n;
	cin>>n;
	for(int i=1;i<n;i++)
	{
		int x,y;
		cin>>x>>y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	dfs(1,0,1);
	solve(1,0);
	cout<<dp[1]<<endl;
//	cout<<(1-bas%mod+mod)%mod;
}
K Center
题意
给多个点,询问最少增加多少个点,使得这些点有一个中心点。
分析
枚举任意两个点,求他们的中心点,用map存每个中心点对应的点数,最后选择那个最多的。
代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1005;
map<pair<int,int> ,int>mp;
pair<int,int>a[MAXN];
int ans=0;
int main()
{
	ios::sync_with_stdio(false);
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].first>>a[i].second;
		a[i].first*=2;
		a[i].second*=2;
		mp[a[i]]++;
		ans=max(ans,mp[a[i]]);
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=i+1;j<=n;j++)
		{
			int X=a[i].first+a[j].first,Y=a[i].second+a[j].second;
			X/=2,Y/=2;
			pair<int,int>p=make_pair(X,Y);
			mp[p]+=2;
			ans=max(ans,mp[p]);
		}
	}
	cout<<n-ans<<endl;
}
M Longest subsequence
题意
给定两个串S和T,求S的一个最长子序列满足字典序严格大于T。
代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+50;
const int inf=-1e6;
int ans=-1;
char s[MAXN],t[MAXN];
int cnt[MAXN][30];
int n,m;
int solve(int i,int j)
{
	if(j>m && i<=n)	return n-i+1;
	if(i>n)return inf;
	int x=t[j]-'a';
	int p1=cnt[i][x];
//	cout<<i<<' '<<j<<' '<<p1<<endl;
	if(p1==0)	return inf;
	if(s[p1]>t[j])return n-p1+1;
	else if(s[p1]==t[j])
	{
		int y=x+1;
		int p2=cnt[i][y];
//		cout<<i<<' '<<j<<' '<<p1<<' '<<p2<<"????"<<endl;
		if(p2==0) return solve(p1+1,j+1)+1;
		else return max(n-p2+1,solve(p1+1,j+1)+1);
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m;
	cin>>s+1>>t+1;
	for(int i=n;i>=1;i--)
	{
		int x=s[i]-'a';
		for(int j=x;j>=0;j--)
		{
			cnt[i][j]=i;
		}
		for(int j=x+1;j<26;j++)
		{
			cnt[i][j]=cnt[i+1][j];
		}
	}
	int ans=solve(1,1);
	if(ans<=0)
	cout<<-1<<endl;
	else cout<<ans<<endl;
}
2019icpc徐州网络赛的更多相关文章
- 2019icpc徐州网络赛_I_query
		题意 给定一个序列,多次询问区间\([l,r]\)中满足\(min(a[i],a[j])==gcd(a[i],a[j])\)的数对\((i,j)\)数. 分析 其实就是求区间有倍数关系的数对数. 由于 ... 
- 2019ICPC徐州网络赛 A.Who is better?——斐波那契博弈&&扩展中国剩余定理
		题意 有一堆石子,两个顶尖聪明的人玩游戏,先取者可以取走任意多个,但不能全取完,以后每人取的石子数不能超过上个人的两倍.石子的个数是通过模方程组给出的. 题目链接 分析 斐波那契博弈有结论:当且仅当石 ... 
- 2018 ICPC 徐州网络赛
		2018 ICPC 徐州网络赛 A. Hard to prepare 题目描述:\(n\)个数围成一个环,每个数是\(0\)~\(2^k-1\),相邻两个数的同或值不为零,问方案数. solution ... 
- 线段树+单调栈+前缀和--2019icpc南昌网络赛I
		线段树+单调栈+前缀和--2019icpc南昌网络赛I Alice has a magic array. She suggests that the value of a interval is eq ... 
- 计蒜客 41391.query-二维偏序+树状数组(预处理出来满足情况的gcd) (The Preliminary Contest for ICPC Asia Xuzhou 2019 I.) 2019年徐州网络赛)
		query Given a permutation pp of length nn, you are asked to answer mm queries, each query can be rep ... 
- 2019ICPC南京网络赛A题   The beautiful values of the palace(三维偏序)
		2019ICPC南京网络赛A题 The beautiful values of the palace https://nanti.jisuanke.com/t/41298 Here is a squa ... 
- ICPC 2019 徐州网络赛
		ICPC 2019 徐州网络赛 比赛时间:2019.9.7 比赛链接:The Preliminary Contest for ICPC Asia Xuzhou 2019 赛后的经验总结 // 比赛完才 ... 
- [徐州网络赛]Longest subsequence
		[徐州网络赛]Longest subsequence 可以分成两个部分,前面相同,然后下一个字符比对应位置上的大. 枚举这个位置 用序列自动机进行s字符串的下标转移 注意最后一个字符 #include ... 
- 徐州网络赛B-BE,GE or NE【记忆化搜索】【博弈论】
		In a world where ordinary people cannot reach, a boy named "Koutarou" and a girl named &qu ... 
随机推荐
- [Jenkins]Job中如何传递自定义变量
			场景一: Job构建步骤间的变量传递 Jenkins提供了数十种构建方式,我们以最常用的『Execute shell』为例.有时为了使Job中的复杂的构建流程更加清晰我们配置多个构建步骤像下面这样.图 ... 
- python实现一个朴素贝叶斯分类方法
			1.公式 上式中左边D是需要预测的测试数据属性,h是需要预测的类:右边式子分子是属性的条件概率和类别的先验概率,可以从统计训练数据中得到,分母对于所有实例都一样,可以不考虑,所有只需 ,返回最大概率的 ... 
- mysql 查询近三个月数据
			select * from t_user where time>DATE_SUB(CURDATE(), INTERVAL 1 WEEK) --一周 select * from t_user wh ... 
- WebSocket 结合 Nginx 实现域名及 WSS 协议访问-Nginx配置
			特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ... 
- oracle存储过程及sql优化-(三)
			接下来介绍上篇接触到的存储过程中的sql语句 insert into TMP_GT3_sbfgl_WJSTJB SELECT NSR.NSRSBH, NSR.NSRMC, NSR.SCJYDZ, ca ... 
- swift模式和模式匹配
			模式和模式匹配 模式: 代表单个或者复合值得结构,也就是说模式不是一个特定的值,它是一种抽象的结构,[一句话,不是特指,是泛指].这样就可以用模式来匹配各种各样的值. 例如:(x,y)可以匹配元祖(1 ... 
- Docker报错: TLS handshake timeout”。
			Docker 默认拉取国外镜像,换成国内就搞定. 为了永久性保留更改,您可以修改 /etc/docker/daemon.json 文件并添加上 registry-mirrors 键值. { &quo ... 
- ffmpeg修复时间戳
			ffmpeg -re -i e:/media/baifa.mp4 -filter_complex -hls_wrap -hls_time d:/demo/hls/cctv13/playlist.m3u ... 
- 1.2.1 Maven到底是什么鬼
			解释之前,提1个小问题. 1.1.假如你正在Eclipse下开发两个Java项目,姑且把它们称为A.B,其中A项目中的一些功能依赖于B项目中的某些类,那么如何维系这种依赖关系的呢? 很简单,这不就是跟 ... 
- Object 源码阅读
			Object 源码阅读 /** * Object 类是类继承结构的根类,每一个类型都以 Object 作为其父类,包括数组. */ public class Object { private stat ... 
