队友打的 思路是连续四个数就可以构造为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题(计算几何模拟)
待补