版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lingzidong/article/details/84726702
J How Much Memory Your Code Is Using?
直接模拟,比较简单。
G. Best ACMer Solves the Hardest Problem
赛后参考了sjf大佬的解法,想了一下的确是自己SB了……
首先题目中要求的是正好等于sqrt(k)的点,可想而知这些点真的不多。
我们先处理出来
每个c存一组a,b。
之后我们操作3,4,也就是要找
也就是说我现在知道每个x-x0的绝对值是什么,有几个,算上y的话,1每种绝对值就有种情况,暴力一下就行了。
有个非常重要的优化,我们记录一下添加进去和一开始就有的点,因为只有这些点的值发生了变化,我们就不用每次清空二维数组了。
#include <bits/stdc++.h>
#include <cstring>
#define ll long long
#define next fuck
#define fi first
#define se second
using namespace std;
const int MAXN = 6000;
bool vis[MAXN+10][MAXN+10];
int val[MAXN+10][MAXN+10];
vector<pair<int,int> > f[10000010];
vector<pair<int,int> > tot;
int dx[4] = {1,1,-1,-1};
int dy[4] = {1,-1,-1,1};
int main()
{
for(int i =0;i<=MAXN;i++)
{
for(int j = 0;j<=MAXN;j++)
{
if(i*i+j*j<=10000000) f[i*i+j*j].emplace_back(i,j);
else break;
}
}
int ca,cat = 1;
scanf("%d",&ca);
while(ca--)
{
int n,m;
scanf("%d%d",&n,&m);
tot.clear();
int op,x,y,w,k;
ll last = 0,ans = 0;
for(int i = 0;i<n;i++)
{
scanf("%d%d%d",&x,&y,&w);
vis[x][y] = 1;
val[x][y] = w;
tot.push_back(make_pair(x,y));
}
printf("Case #%d:\n",cat++);
auto check = [&](int x,int y)
{
return x >= 1 && x<= MAXN && y >= 1 && y <= MAXN && vis[x][y] == 1;
};
set<pair<int,int> > s;
while(m--)
{
s.clear();
scanf("%d%d%d",&op,&x,&y);
x = (x + last) % 6000 + 1;
y = (y + last) % 6000 + 1;
// cout<<x<<' '<<y<<endl;
if(op == 1)
{
scanf("%d",&w);
vis[x][y] = 1;
val[x][y] = w;
tot.push_back(make_pair(x,y));
}
else if(op == 2)
{
vis[x][y] = 0;
val[x][y] = 0;
}
else if(op == 3)
{
scanf("%d%d",&k,&w);
for(auto &it : f[k])
{
for(int i = 0;i<4;i++)
{
int xx = x - it.fi*dx[i];
int yy = y - it.se*dy[i];
if(check(xx,yy)) s.insert(make_pair(xx,yy));
}
}
for(auto &it : s) val[it.fi][it.se] += w;
}
else
{
scanf("%d",&k);
last = 0;
for(auto it : f[k])
{
for(int i = 0;i<4;i++)
{
int xx = x - it.fi*dx[i];
int yy = y - it.se*dy[i];
if(check(xx,yy)) s.insert(make_pair(xx,yy));
}
}
for(auto &it : s) last += val[it.fi][it.se];
printf("%lld\n",last);
//last = ans;
}
}
for(auto it : tot)
{
vis[it.fi][it.se] = val[it.fi][it.se] = 0;
}
}
return 0;
}
C. Insertion Sort
正解好像不是找规律呢
打个表,发现每个答案可以写成
的样子,分析一下nk只有50,不用求逆元来求等差数列了。
注意如果 n<=k 就直接是n!
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
int ca,cat = 1;
scanf("%d",&ca);
while(ca--)
{
ll n,k,mod;
scanf("%lld%lld%lld",&n,&k,&mod);
ll nk = 1LL;
ll mk = 1LL;
if(k > n) k = n;
for(ll i = 2LL;i<=k;i++)
{
nk = (nk *i) % mod;
}
for(ll i = 2LL;i<=k-1;i++)
{
mk = (mk*i) % mod;
}
ll kk = k*k % mod;
ll b1 = kk*mk % mod;
ll d1 = 2LL*nk%mod;
ll sumb = 0,bi = b1;
for(int i = 0;i<=n-k-1;i++)
{
//cout<<bi<<endl;
sumb = (sumb + bi) % mod;
bi = (bi + d1) % mod;
}
//cout<<nk<<' '<<sumb<<endl;
ll ans = nk + sumb % mod;
if(n == k)
{
printf("Case #%d: %lld\n",cat++,nk%mod);
}
else printf("Case #%d: %lld\n",cat++,ans%mod);
}
return 0;
}