文章目录
Codeforces Round #533 (Div. 2) C. Ayoub and Lost Array &DP
http://codeforces.com/contest/1105/problem/C
题意:
给n,l,r。
一个n长的数组每个位置可以填区间l-r的值。
有多少种填法,使得数组每个位置相加的和是3的倍数
dp,
从1个数组扩展到n个数组,
dp[i][j]是加上第i个数组后,分别余0,1,2的个数。
#include <bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
long long dp[200005][3];
int main()
{
int n,l,r;
while(cin>>n>>l>>r)
{
memset(dp,0,sizeof(dp));
dp[0][0]=1,dp[0][1]=0,dp[0][2]=0;
int x,y,z;
x=r/3-(l-1)/3,y=(r+2)/3-(l+1)/3,z=(r+1)/3-l/3;
//余0则是,i-1余0*自己余0+(i-1余1*自己余2)+(i-1余2*自己余1
for(int i=1;i<=n;i++)
{
dp[i][0]=dp[i-1][0]*x%mod+dp[i-1][1]*z%mod+dp[i-1][2]*y%mod;
dp[i][0]%=mod;
dp[i][1]=dp[i-1][0]*y%mod+dp[i-1][1]*x%mod+dp[i-1][2]*z%mod;
dp[i][1]%=mod;
dp[i][2]=dp[i-1][0]*z%mod+dp[i-1][1]*y%mod+dp[i-1][2]*x%mod;
dp[i][2]%=mod;
}
cout<<dp[n][0]<<endl;
}
}
Codeforces Round #533 (Div. 2) D. Kilani and the Game
http://codeforces.com/contest/1105/problem/D
题意:
给n*m的地图,最多9个人,同时有每个人的扩张次数(我开始以为是直线扩张最大长度。。实际是能连续扩张次数。)
地图上有‘#’,‘.’,和数字,数字对应每个人的据点,
从1-n轮流扩张。
地图被扩张完后,输入每个人的据点数目。
垃圾题目 浪费时间 毁我青春。。
注意一点,当矩阵的空间不再减少时候直接结束
#include <bits/stdc++.h>
using namespace std;
int a[15];
int grp[1005][1005];
struct node
{
node (int xx,int yy)
{
x=xx;
y=yy;
}
int x,y;
};
int n,m,p;
vector<node> node_bfs[15];
vector<node >tem[2];
int s_sum;
int dfs(int depth,int max_depth,int bl,int num)
{
// cout<<"num "<<num<<' '<<depth<<endl;
if(depth==max_depth) return bl;
tem[!bl].clear();
int z=0;
for(int i=0;i<tem[bl].size();i++)
{
for(int x=-1;x<=1;x++)
{
for(int y=-1;y<=1;y++)
{
if(abs(x)!=abs(y))
{
int xv=tem[bl][i].x+x;
int yv=tem[bl][i].y+y;
// cout<<"xx yy "<<num<<' '<<xv<<' '<<yv<<' '<<grp[xv][yv]<<endl;
// cout<<x<<' '<<y<<endl;
if(xv>0&&xv<=n&&yv>0&&yv<=m&&!grp[xv][yv])
{
z=1;
s_sum--;
grp[xv][yv]=num;
tem[!bl].push_back(node(xv,yv));
}
}
}
}
}
if(z)
{
return dfs(depth+1,max_depth,!bl,num);
}
else
{
tem[!bl].clear();
return !bl;
}
}
int main()
{
while(cin>>n>>m>>p)
{
s_sum=0;
for(int i=1;i<=p;i++)
{
node_bfs[i].clear();
cin>>a[i];
}
string s;char c;
for(int i=1;i<=n;i++)
{
cin>>s;
for(int j=1;j<=m;j++)
{
c=s[j-1];
//cin>>c;
if(c=='.')
{
grp[i][j]=0;
s_sum++;
}
else if(c!='#')
{
int v=c-'0';
grp[i][j]=v;
node_bfs[v].push_back(node(i,j));
}
else
{
grp[i][j]=-1;
}
}
}
while(s_sum)
{
int qs=s_sum;
// cout<<s_sum<<endl;
for(int i=1;i<=p;i++)
{
tem[0]=node_bfs[i];
int res=dfs(0,a[i],0,i);
node_bfs[i]=tem[res];
//swap(&node_bfs[i],&tem[res]);
}//cout<<endl;
if(qs==s_sum) break;
}
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
a[grp[i][j]]++;
//cout<<grp[i][j]<<' ';
}
// cout<<endl;
}
for(int i=1;i<=p;i++)
{
cout<<a[i]<<' ';
}
cout<<endl;
}
}
标题 532 div2 F. Ivan and Burgers 线性基
http://codeforces.com/contest/1100/problem/F
题目大意:有n个汉堡店,每个店里最贵的汉堡是ci元,q次询问,从l到r,所能花费的最多钱数(结束与开始时的金额差),但是花钱不是直接的加减,规则是手里有d元,要花费c元,那支付只后,他还有d^c元。开始是他有非常多个1(rich)。
具体思路:贪心,我们按照右边界的大小进行排序,小的在上面,大的往下安排,然后每一次我们寻找1–> r区间内的线性基,如果当前的线性基能往后移动,我们就选取后面的这个线性基(因为我们对输入的数据进行了排序,后面的r肯定是大的,所以我们将选取的线性基尽量的往后安排肯定是没有问题的,然后我们查询的时候,看一下当前位上有线性基的时候,先判断这个线性基取的时候是从哪个数里面取出来的,然后再看一下这个数是不是大于l的,如果是的话,这个线性基就是可用的,我们通过这些线性基寻找一个最大值就可以了)
最后解题思路就是离线的线性基。
然后 查询l 到r 区间中的最大值是谁 从高位到低位便利
#include <bits/stdc++.h>
using namespace std;
const int maxn=500005;
int nums[maxn];
struct node
{
int l,r;
int vis;
}tag[maxn];
bool cmp1(node a,node b)
{
if(a.r==b.r) return a.l<b.l;
return a.r<b.r;
}
int a[25],pos[25];
bool liner(int val,int p)
{
for (int i=20;i>=0;i--)
{
if (val&(1LL<<i))
{
if (!a[i])
{
a[i]=val;
pos[i]=p;
break;
}
if(pos[i]<p)
{
swap(pos[i],p);
swap(a[i],val);
}
val^=a[i];
}
}
//cout<<"liner "<<val<<endl;
return val>0;
}
int query_maxs(int l)
{
int ret=0;
for (int i=20;i>=0;i--)
if ((ret^a[i])>ret&&pos[i]>=l)
ret^=a[i];
return ret;
}
int ans[maxn];
int ces[maxn];
int main()
{
int n;
while(cin>>n)
{
for(int i=1;i<=n;i++)
{
// cin>>ces[i];
scanf("%d",&ces[i]);
}
int q;
// cin>>q;
scanf("%d",&q);
for(int i=0;i<q;i++)
{
//cin>>tag[i].l>>tag[i].r;
scanf("%d%d",&tag[i].l,&tag[i].r);
tag[i].vis=i;
}
sort(tag,tag+q,cmp1);
int r=1;
for(int i=0;i<q;i++)
{
while(r<=tag[i].r)
{
liner(ces[r],r);
r++;
}
// cout<<"ads a "<<query_maxs(tag[i].l)<<' '<<tag[i].l<<' '<<tag[i].r<<' '<<r<<endl;
ans[tag[i].vis]=query_maxs(tag[i].l);
}
for(int i=0;i<q;i++)
{
cout<<ans[i]<<endl;
}
}
}
标题 Educational Codeforces Round 58 (Rated for Div. 2)F. Trucks and Cities
http://codeforces.com/contest/1101/problem/F
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 405;
int dp[maxn][maxn]; // dp[i][j][k] 表示从i出发到达j中间停留k次的最长间隔。
int a[maxn];
int pos[maxn];
struct data
{
int f,c,r;
data(){}
data(int ff,int cc,int rr)
{
f=ff;
c=cc;
r=rr;
}
};
vector<data> G[maxn];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++)
{
int s,f,c,r;
scanf("%d%d%d%d",&s,&f,&c,&r);
G[s].push_back(data(f,c,r));//离线处理每个起点为s的查询
}
ll ans=0;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
dp[j][0]=a[j]-a[i];
int pos=0;
for(int k=1;k<=n;k++)
{
dp[j][k]=a[j]-a[i];
while(pos+1<=j&&dp[pos+1][k-1]<a[j]-a[pos+1]) pos++;//单调队列优化DP
dp[j][k]=min(dp[j][k],min(a[j]-a[pos],dp[pos+1][k-1]));
}
}
for(int j=0;j<G[i].size();j++)
{
int f=G[i][j].f;
int c=G[i][j].c;
int r=G[i][j].r;
ans=max(ans,1LL*dp[f][r]*c);
}
}
printf("%lld\n",ans);
return 0;
}
G. (Zero XOR Subset)-less
Educational Codeforces Round 58 (Rated for Div. 2)
http://codeforces.com/contest/1101/problem/G
解题思路 线性基的性质
#include <bits/stdc++.h>
using namespace std;
int a[200005],p[66];
void Linear(int x)
{
int xe=x;
// cout<<x<<endl;
for(int i=31;i>=0;i--)
{
if((x&(1<<i))==0) continue ;
if(p[i]==0)
{
p[i]=x;
break;
}
else x^=p[i];
//cout<<"asd "<<i<<' '<<x<<' '<<xe<<endl;
}
}
int main()
{
int n;
while(cin>>n)
{
memset(p,0,sizeof(p));
int t=0;
for(int i=0;i<n;i++)
{
cin>>a[i];
if(i==0) t=a[i];
else t^=a[i];
}
if(t==0 )
{
cout<<-1<<endl;
continue;
}
else
{
for(int i=0;i<n;i++)
{
Linear(a[i]);
}
int ans=0;
for(int i=31;i>=0;i--)
{
if(p[i])
{
ans++;
// cout<<i<<' '<<p[i]<<endl;
}
}
cout<<ans<<endl;
}
}
}