"山大地纬杯”第十二届山东省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题(计算几何模拟)

待补

posted @ 2022-05-30 15:28  wzx_believer  阅读(148)  评论(0)    收藏  举报