第一套题
1 CFGym 101853G Hard Equation
BSGS 算法的模板题 (题目中给的那个最后一个样例结果也可以是0)
[关于bsgs算法学习的链接1](http://blog.miskcoo.com/2015/05/discrete-logarithm-problem)
[关于bsgs算法学习的链接2](https://blog.csdn.net/lycheng1215/article/details/79047734)
[关于bsgs算法学习的链接3](https://ksmeow.moe/baby_step_giant_step/)
第二套题 (The 18th Zhejiang University Programming Contest Sponsored)
1 F-Schrödinger’s Knapsack
准确的来说这道题是一道背包,但是它的价值会变,当时就做成sb了淦
容易猜出来无论先装啥都要先装背包占比小的 所以排序
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
ll a, b, c, t, i, j, ans, n1, val, n2, q[2005], w[2005], dp[2005][2005];
ll s[2005][2005];
int main()
{
while (~scanf("%lld", &t))
{
while (t--)
{
scanf("%lld%lld%lld", &a, &b, &val);
scanf("%lld%lld", &n1, &n2);
for (i = 0; i < n1; i++)
{
scanf("%lld", &q[i]);
}
for (i = 0; i < n2; i++)
{
scanf("%lld", &w[i]);
}
for(i=0;i<=n1;i++)
for(j=0;j<=n2;j++)
s[i][j]=dp[i][j]=0;
sort(q, q + n1);
sort(w, w + n2);
for (i = 0; i <= n1; i++)
{
if (i == 0)
s[0][0] = val;
else
s[i][0] = s[i - 1][0] - q[i - 1];
if (s[i][0] <= 0)
break;
for (j = 1; j <= n2; j++)
{
s[i][j] = s[i][j - 1] - w[j - 1];
if (s[i][j] <= 0)
break;
}
}
ans = 0;
for (i = 0; i <= n1; i++)
{
for (j = 0; j <= n2; j++)
{
if (s[i][j] <= 0)
break;
if (i > 0)
{
dp[i][j] = max(dp[i][j], dp[i - 1][j] + s[i][j] * a);
}
if (j > 0)
{
dp[i][j] = max(dp[i][j], dp[i][j - 1] + s[i][j] * b);
}
ans = max(ans, dp[i][j]);
}
}
printf("%lld\n", ans);
}
}
return 0;
}
G-Pretty Matrix
着个题是一个广搜,太菜了想不通问队友就简单搜索标记搞就完事了…
注意 这题是n*m<1e5 所以等输入后再开辟数组 (vector好像也行队友用的vector 但是我试的好像不行 不知道是不是我的问题)
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
struct qwe
{
int a, b;
int flag;
bool operator<(const qwe &a1) const
{
if (a == a1.a && b == a1.b)
return flag < a1.flag;
if (a == a1.a)
return b < a1.b;
return a < a1.a;
}
};
struct qwe1
{
int a, b;
int val;
};
int t, n, m, ans, a, b, c, d;
int solve(int n,int m)
{
int v[n+1][m+1];
int i, j, d;
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
scanf("%d", &v[i][j]);
}
}
scanf("%d%d%d%d", &a, &b, &c, &d);
int flag, d1;
queue<qwe1> q1;
map<qwe, int> m1;
struct qwe1 a1;
struct qwe b1;
a1.a = a;
a1.b = b;
a1.val = 0;
q1.push(a1);
while (!q1.empty())
{
a1 = q1.front();
q1.pop();
d1 = a1.val;
b1.a = a1.a;
b1.b = a1.b;
flag = (v[a1.a - 1][a1.b - 1] + d1) % 2;
b1.flag = flag;
//cout<<a1.a<<" "<<a1.b<<endl;
//cout<<m1.count(b1)<<" "<<q1.size()<<endl;
if (m1.count(b1) != 0)
continue;
if (a1.a == c && a1.b == d)
return a1.val;
m1[b1] = 1;
if (flag)
{
struct qwe1 tmp;
tmp = a1;
tmp.val = a1.val + 1;
if (a1.b + 1 <= m)
{
tmp.b = a1.b + 1;
q1.push(tmp);
}
if (a1.b - 1 > 0)
{
tmp.b = a1.b - 1;
q1.push(tmp);
}
}
else
{
struct qwe1 tmp;
tmp = a1;
tmp.val = a1.val + 1;
if (a1.a + 1 <= n)
{
tmp.a = a1.a + 1;
q1.push(tmp);
}
if (a1.a - 1 > 0)
{
tmp.a = a1.a - 1;
q1.push(tmp);
}
}
}
return -1;
}
int main()
{
while (~scanf("%d", &t))
{
while (t--)
{
scanf("%d%d", &n, &m);
ans=solve(n,m);
printf("%d\n",ans);
}
}
return 0;
}
第三套(The 15th Zhejiang Provincial Collegiate Programming Contest Sponsored)
E - LIS
贪心就完事了 gtmd 还是太菜了不会
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#define mod 1000000000
using namespace std;
typedef long long LL;
struct qwe {
LL num,i;
LL r,l;
LL first;
}q[100005];
int cmp(struct qwe a,struct qwe b)
{
if(a.i==b.i)
return a.num>b.num;
return a.i<b.i;
}
LL ans[100005],next1[100005],n,i,j,L,t;
int main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&n);
memset(ans,0,sizeof(ans));
for(i=0;i<n;i++)
{
scanf("%lld",&q[i].i);
q[i].num=i;
q[i].first=next1[q[i].i-1];
next1[q[i].i]=i;
}
for(i=0;i<n;i++)
{
scanf("%lld%lld",&q[i].l,&q[i].r);
}
sort(q,q+n,cmp);
L=0;
for(i=0;i<n;i++)
{
//cout<<ans[q[i].first]<<" ";
if(i==0)
ans[q[i].num]=L=q[i].l;
else
{
if(q[i].i!=q[i-1].i)
{
L=ans[q[i].first]+1;
//cout<<q[i].num<<" "<<q[i].i<<" "<<q[i].l<<" "<<q[i].r<<" "<<L<<endl;
ans[q[i].num]=L=max(q[i].l,L);
}
else
{
//cout<<q[i].num<<" "<<q[i].i<<" "<<q[i].l<<" "<<q[i].r<<" "<<L<<" "<<ans[q[i].first]+1<<endl;
ans[q[i].num]=L=max(L,max(q[i].l,ans[q[i].first]+1));
}
}
//cout<<ans[q[i].num]<<endl;
}
printf("%lld",ans[0]);
for(i=1;i<n;i++)
{
printf(" %lld",ans[i]);
}
printf("\n");
}
return 0;
}
F-Now Loading!!!
玛格级 想出这题的人都不是一般人 我是真想不出来 因为题给的数据范围太大就现将结果打表在后面输入查询的时候直接二分查表就行了 哔~哔~哔~(因不明原因屏蔽)
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#define mod 1000000000
using namespace std;
typedef long long LL;
LL t, i, j, n, ans, dd, dd1, dd2, a, b;
LL q[500050];
LL w, ans1, l, r, mid;
LL sum[32][500050];
int main()
{
scanf("%lld", &t);
while (t--)
{
scanf("%lld%lld", &a, &b);
for (i = 1; i <= a; i++)
scanf("%lld", &q[i]);
sort(q + 1, q + a + 1);
for (j = 1; j <= 30; j++)
for (i = 1; i <= a; i++)
{
sum[j][i] = sum[j][i-1] + q[i] / j;
}
ans = 0;
for (j = 1; j <= b; j++)
{
scanf("%lld", &w);
dd = 1;//k
ans1 = 0;//temp
dd1 = 0;//pos
dd2 = w;//up
for (i = 1; i <= a; i = dd1 + 1)
{
dd1 = i - 1;
l = i;
r = a;
while (l <= r)
{
mid = (l + r) >> 1;
if (q[mid] <= dd2)
{
dd1 = mid;
l = mid + 1;
}
else
{
r = mid - 1;
}
}
ans1 = (ans1 + sum[dd][dd1] - sum[dd][i-1] + mod) % mod;
dd++;
dd2 *= w;
}
ans = (ans + ans1 * j) % mod;
}
printf("%lld\n", (ans + mod) % mod);
}
return 0;
}
I-Magic Points
题意是对n*n的正方形取边上的点 连线不能平行x和y轴 问前 n条边连线交点最多的 就i和i+n就完事了 但是 最后一个点 会和之前的点有重复 所以 最后一点 要重新找
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
int t,i,j,n;
int main()
{
while (~scanf("%d", &t))
{
while(t--)
{
scanf("%d",&n);
if(n==2)
printf("0 2 1 3");
else
{
for(i=0;i<n-1;i++)
{
printf("%d %d ",i,i+n);
}
printf("%lld %lld",n-1,3*n-4);
}
printf("\n");
}
}
return 0;
}
第四套
F - Never Wait for Weights
这题是个并查集 比赛 时候想到了 但是 犯蠢 减错了权值 ( 还是太菜 学不来
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#define eps 0.0000000001
#define mem(a) memset(a,0,sizeof(a))
#define maxx 1e10
#define inf 0x3f3f3f3f
#define PI acos(-1)
#define show(a) cout<<a<<endl
//#define show(a,b) cout<<a<<" "<<b<<endl
using namespace std;
typedef long long ll;
ll father[100005],val1[100005];
ll Find(ll x)
{
ll t=x,d=x,sum=0,sum1;
while(x!=father[x])
{
sum+=val1[x];
x=father[x];
}
sum+=val1[x];
//cout<<"***"<<sum<<endl;
while(x!=t)
{
d=father[t];
father[t]=x;
sum1=val1[t];
val1[t]=sum;
t=d;
sum=sum-sum1;
}
return x;
}
void Union(ll x,ll y,ll v)
{
ll fx=Find(x);
ll fy=Find(y);
if(fx!=fy)
{
father[fx]=fy;
val1[fx]=v+val1[y]-val1[x];
}
}
ll n,m,val,i,j,a,b,ans;
char q[20];
int main()
{
while(~scanf("%lld%lld",&n,&m))
{
if(n==0&&m==0)
break;
for(i=1;i<=n;i++)
father[i]=i;
memset(val1,0,sizeof(val1));
for(i=0;i<m;i++)
{
scanf(" %s",q);
if(q[0]=='!')
{
scanf("%lld%lld%lld",&a,&b,&val);
Union(a,b,val);
}
else
{
scanf("%lld%lld",&a,&b);
if(Find(a)!=Find(b))
{
printf("UNKNOWN\n");
}
else
{
ans=val1[b]-val1[a];
printf("%lld\n",-ans);
}
}
}
}
}