• "山大地纬杯”第十二届山东省ICPC大学生程序设计竞赛


    队友打的 思路是连续四个数就可以构造为0 例如 +7 -8 -9 +10

    所以只要将前面的数字组合成17后面的连续四个为0

    #include<bits/stdc++.h>
    using namespace std;
    
    int main ()
    {
        int n;
        cin >> n;
        if (n < 4)
        {
            printf("-1");
            return 0;
        }
        if(n==5){
            cout<<"5*2+3+4*1";
            return 0;
        }
        if(n==4){
            cout<<"3*(2+4)-1";
            return 0;
        }
        int f = 1; 
        if ((n-6)%4 == 0)
        {
            printf("1-2-3*4+5*6");
            for (int i = 7; i <= n; i++)
            {
                if (f == 1 || f == 4){
                    printf("+");
                    if (f == 4)f = 0;
                }
                else
                {
                    printf("-");    
                }
                printf("%d", i);
                f++;
            }
        }
            if ((n-7)%4 == 0)
        {
            printf("1*2+3+4-5+6+7");
            for (int i = 8; i <= n; i++)
            {
                if (f == 1 || f == 4){
                    printf("+");
                    if (f == 4)f = 0;
                }
                else
                {
                    printf("-");  
                }
                printf("%d", i);
                f++;
            }
        }
            if ((n-8)%4== 0)
        {
            printf("1-2*3-4-5*6+7*8");
            for (int i = 9; i <= n; i++)
            {
                if (f == 1 || f == 4){
                    printf("+");
                    if (f == 4)f = 0;
                }
                else
                {
                    printf("-");    
                }
                printf("%d", i);
                f++;
            }
        }
            if ((n-9)%4 == 0)
        {
            printf("1+2+3+4-5+6+7+8-9");
            for (int i = 10; i <= n; i++)
            {
                if (f == 1 || f == 4){
                    printf("+");
                    if (f == 4)f = 0;
                }
                else
                {
                    printf("-");    
                }
                printf("%d", i);
                f++;
            }
        }
    }
    


    首先这个题n三方是可以做的 就是一个区间dp 当然还要打高精度

    但是问题只能n方做 发现这个题目的性质 发现加号恰好均分长度才能最小化

    所以就能避免很多无用的转移

    复杂度:n×m × n/m

    #include<bits/stdc++.h>
    using namespace std;
    int a[1005];
    struct big_num{
    	vector<int>a;
    	big_num operator +(big_num &b){
    		int n=a.size(),m=b.a.size();
    		big_num c;
    		if(!n||!m) return c;
    		c.a.resize(max(n,m)+1);
    		for(int i=0;i<n;i++) c.a[i]+=a[i];
    		for(int i=0;i<m;i++) c.a[i]+=b.a[i];
    		for(int i=0;i<c.a.size();i++) if(c.a[i]>9) c.a[i+1]++,c.a[i]-=10;
    		n=c.a.size()-1;
    		while(!c.a.empty()&&!c.a[n]) c.a.pop_back(),n--;
    		return c;
    	}
    	void print(){
    		for(int i=a.size()-1;~i;i--) printf("%d",a[i]);
    		puts("");
    	}
    }f[1002][1002];
    big_num min(big_num &a,big_num b){
    	int n=a.a.size(),m=b.a.size();
    	if(!n) return b;
    	if(!m) return a;
    	if(n>m) return b;
    	if(n<m) return a;
    	else for(int i=n-1;~i;i--) if(a.a[i]<b.a[i]) return a;
    	else if(a.a[i]>b.a[i]) return b;
    	return a;
    }
    big_num num(int l,int r){
    	big_num b;
    	for(int i=r;i>=l;i--) b.a.push_back(a[i]);
    	return b;
    }
    int main(){
    	int n,m;
    	cin>>n>>m,m++;
    	for(int i=1;i<=n;i++) scanf("%1d",&a[i]);
    	int s=ceil(1.0*n/m+3);
    	f[0][0].a.push_back(0);
    	for(int i=1;i<=n;i++){
    		int M=min(i,m);
    		for(int j=1;j<=M;j++){
    			for(int k=max(1,i-s);k<=i;k++)
    				f[i][j]=min(f[i][j],num(k,i)+f[k-1][j-1]);
    		}
    	}
    	f[n][m].print();
    }
    

    不考虑0的情况 就用一个map和前缀乘积就可以

    考虑0的情况 就相当于分别处理每一段不为0的连续段

    考虑x=0的情况 就相当于选择一个子串 子串乘积为0的个数

    这里有两种算法

    一个是容斥 乘积为0 =所有子串 - 乘积不为0

    一个是直接推 比如 123 0 1233 0 1

    答案就是 4×7 + 5×2

    最后一定注意注意!!!!答案不能取模 !!!!就是因为这个我们队一直卡在这里

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int maxn=5e5+5;
    const int mod=998244353;
    #define int ll
    ll a[maxn],pre[maxn],ans;
    map<ll,int>Q;
    ll ksm(ll aa,ll bb){
    	ll res=1;
    	while(bb){
    		if(bb&1)res=res*aa%mod;
    		bb>>=1;
    		aa=aa*aa%mod;
    	}
    	return res;
    }
    ll n,x;
    signed main(){
        cin>>n>>x;
        pre[0]=1;
        for(int i=1;i<=n;i++){
        	scanf("%lld",&a[i]);
        	if(!a[i]){
        		pre[i]=0;
        		continue;
    		}
        	if(pre[i-1])
        	pre[i]=pre[i-1]*a[i]%mod;
        	else pre[i]=a[i];
    	}	
    	if(!x){
    		ll last=0;
    		for(ll i=1;i<=n;i++){
    			if(a[i])continue;
    			ans+=(i-last)*(n-i+1);
    			last=i;
    		}
    		cout<<ans<<endl;
    		return 0;
    	}
    	ll mi=ksm(x,mod-2);
    	Q[1]=1;
        for(int i=1;i<=n;i++){
        	if(!a[i]){
        		Q.clear();
    			Q[1]=1;
        		continue;
    		}
        	ll t=pre[i]*mi%mod;
        	int res=Q.count(t);
    		if(res) 
        	ans=ans+Q[t];
        	Q[pre[i]]++;
    	}
    	cout<<ans<<endl;
        return 0;
    }
    

    很明显的模拟题 但是细节没处理好

    发现越学到后面反而会把简单问题复杂化了 因为每次都要清空所有map 所以一定是会超时超空间的

    因为每次改变的只有n个 所以每次只将改变的清零 压根不用map 计算的话用(n-1)×n/2 或者累加都可以

    #include<bits/stdc++.h>
    #define endl '\n'
    using namespace std;
    
    const int N = 3010;
    
    int n, m, k, t;
    pair<int, int> pos[N];
    int ans[N][N];
    string s[N];
    
    void solve(){
        int res = 0;
        for(int i = 1; i <= k; ++ i){
            res += ans[pos[i].first][pos[i].second];
            ans[pos[i].first][pos[i].second] += 1;
        }
        for(int i = 1; i <= k; ++ i){
            ans[pos[i].first][pos[i].second] = 0;
        }
        cout << res << endl;
    }
    int main(){
        cin >> n >> m >> k >> t;
        for(int i = 1; i <= k; ++ i)    cin >> pos[i].first >> pos[i].second;
        for(int i = 1; i <= k; ++ i)    cin >> s[i];
        int cnt = -1;
        solve();
        for(int i = 0; i < t; ++ i){
            for(int j = 1; j <= k; ++ j){
                char c = s[j][i];
                if(c == 'D')    pos[j].first += 1;
                else if(c == 'U')    pos[j].first -= 1;
                else if(c == 'L')    pos[j].second -= 1;
                else if(c == 'R')    pos[j].second += 1;
            }
            solve();
        }
        return 0;
    }
    

    第一次和队友打比赛经验不是很足 还有就是偷懒了 其实都想到了后面都选A 但是就没去打

    开一个较小的数据打表就会发现 后面都是选A的

    #include<bits/stdc++.h>
    using namespace std;
    #define lowbit(x) x&(-x)
    #define ll long long
    int dp1[5000],dp2[5000];
    int a[5]={0,2,3,17,19};
    int b[5]={0,5,7,11,13}; 
    void solve();
    int main(){
    	memset(dp1,0x7f,sizeof(dp1));
    	memset(dp2,0x7f,sizeof(dp2));
    	dp1[0]=dp2[0]=0;
    	for(int i=1;i<=5;i++)
    	for(int v=a[i];v<5000;v++)
    	dp1[v]=min(dp1[v],dp1[v-a[i]]+1);
    	for(int i=1;i<=5;i++)
    	for(int v=b[i];v<5000;v++)
    	dp2[v]=min(dp2[v],dp2[v-b[i]]+1);
    	int T;
    	cin>>T;
    	while(T--)solve();
         return 0;
    }
    void solve(){
    	int i;
    	if(i<5000){
    		if(dp1[i]==dp2[i])cout<<"both"<<endl;
    		else if(dp1[i]<dp2[i])cout<<"A"<<endl;
    		else cout<<"B"<<endl;
    	}else cout<<"A"<<endl;
    }
    

    C题(计数类树形dp)

    待补

    J题(计算几何模拟)

    待补

  • 相关阅读:
    【Kubernetes学习之一】Kubernetes 简介
    eclipse&myeclipse 生成jar包后,spring无法扫描到bean定义
    【Docker学习之七】Docker图形化管理和监控
    【Docker学习之六】Docker容器互联
    【Docker学习之五】Docker自定义镜像示例
    【Docker学习之四】Docker自定义容器镜像
    【Docker学习之三】Docker查找拉取镜像、启动容器、容器使用
    【Docker学习之二】Docker部署安装
    Tensorflow之tf.metrics
    pytorch 实现多分类
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/16326936.html
Copyright © 2020-2023  润新知