文章目录
第一场
1001
- 思路
全填 1 1 1 就可
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void solve()
{
ll n;cin>>n;
if(n==1){
cout<<0<<endl;return;
}
ll len=0;ll x=1;
while(x<n){
len++;x*=2;
}
//cout<<len<<endl;
ll ans=pow(2,len-1)-1;
cout<<ans<<endl;
}
int main()
{
int t;cin>>t;
while(t--){
solve();
}
}
1005
- 思路
最小生成树,素数和 2 2 2 连一条边,其他的肯定是一个素数的倍数。所以预处理,素数+上二倍本身,合数+上自己
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e7+10;
const int maxn=1e7+10;//这个是在哪一个范围内
int prime[maxn];
ll ans[N];
int visit[maxn];//1代表是偶数,0代表是奇数
void Prime()
{
visit[1]=1;
ans[2]=0;
for (int i = 2;i <= maxn; i++)
{
if (!visit[i])
{
prime[++prime[0]] = i;
//ans[i]=ans[i-1]+i*2;
}
for (int j = 1; j <=prime[0] && i*prime[j] <= maxn; j++)
{
visit[i*prime[j]] = 1;
if (i % prime[j] == 0)
{
break;
}
}
}
for(int i=3;i<=N;i++){
if(!visit[i]){
ans[i]=ans[i-1]+i*2*1ll;
}
else{
ans[i]=ans[i-1]+i*1ll;
}
}
}
void solve()
{
int n;cin>>n;
cout<<ans[n]<<endl;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
Prime();
int t;cin>>t;
while(t--){
solve();
}
}
1008
- 思路
悬线法或者单调队列
先抽象成 0 , 1 0,1 0,1,然后处理出每一列的单调区间长度,然后每一行相当于找一个最大子长方形
然后就转化成下面这个模型了,用单调栈搞一下。
- 代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e3+10;
int a[N][N];bool b[N][N];
int h[N];
int n,m;
int que[N];
void solve()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
if(i>1){
b[i][j]=(a[i][j]>=a[i-1][j]);
}
}
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(b[i][j]==0){
h[j]=1;
}
else{
h[j]++;
}
}
int tot=0;h[m+1]=0;
for(int j=1;j<=m+1;j++){
while(tot&&h[que[tot]]>h[j]){
ans=max(ans,(j-1-que[tot-1])*h[que[tot]]);
tot--;
}
que[++tot]=j;
}
}
cout<<ans<<endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;cin>>t;
while(t--){
solve();
}
}
1009
- 思路
将边按权值从小到大排序,每一阶段取出同权值的所有边,将这些边的端点用并查集两两合并,若某一阶段的全部边合并完,并查集数量为k,则当前阶段合并边的权值就是答案,否则输出-1。反证法易证。
- 代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=1e6+10;
int T,n,m,k,fa[maxn],now,ans;
struct da{int u,v,w;}q[maxn];
bool cmp(da aa,da bb){return aa.w<bb.w;}
int getf(int x)
{
if (fa[x]==x) return x;
fa[x]=getf(fa[x]);
return fa[x];
}
void solve()
{
scanf("%d%d%d",&n,&m,&k); now=n; ans=0;
for (int i=1;i<=n;i++) fa[i]=i;
for (int i=1;i<=m;i++) scanf("%d%d%d",&q[i].u,&q[i].v,&q[i].w);
sort(q+1,q+m+1,cmp);
for (int i=1;i<=m;i++)
{
if (q[i].w!=q[i-1].w){if (now==k) {printf("%d\n",ans); return;}}
if (getf(q[i].u)==getf(q[i].v)) continue;
now--;
fa[getf(q[i].u)]=getf(q[i].v);
ans=q[i].w;
}
printf("%d\n",now==k?ans:-1);
}
int main()
{
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
scanf("%d",&T);
while (T--) solve();
return 0;
}
1006
- 思路
对数列做前缀异或,将题面转化为找两个距离最近的数,使得他们的异或值不小于
k
k
k。
枚举靠右的那个数,同时维护字母树,字母树每个节点保存范围内最靠右的点的位置。根据
k
k
k 来询问对应的
l
o
g
log
log 个节点,从而更新答案。
效率:
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int inf=1e9;
const int N=1e5+10;
const int M=3e6+10;
const int mo=998244353;
int p[M][2],mx[M],a[N];
void sol(){
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
a[i]^=a[i-1];
}
int anl=-1,anr=n,tot=1;
mx[1]=-1;
p[1][0]=p[1][1]=0;
for(int i=0;i<=n;i++){
int x=1,res=-1;
for(int j=29;j>=0;j--){
int w=(a[i]>>j)&1;
if(!((k>>j)&1)){
if(p[x][w^1]) res=max(res,mx[p[x][w^1]]);
x=p[x][w];
}
else x=p[x][w^1];
if(!x) break;
}
if(x) res=max(res,mx[x]);
if(res>=0&&i-res<anr-anl) anl=res,anr=i;
x=1;
for(int j=29;j>=0;j--){
int w=(a[i]>>j)&1;
if(!p[x][w]){
p[x][w]=++tot;mx[tot]=-1;
p[tot][0]=p[tot][1]=0;
}
x=p[x][w];
mx[x]=max(mx[x],i);
}//
}
if(anl>=0) printf("%d %d\n",anl+1,anr);
else printf("-1\n");
}
int main(){
int t;
//freopen("in.txt","r",stdin);
//freopen("ans.txt","w",stdout);
scanf("%d",&t);
while(t--)
sol();
}
第二场
1001
- 思路
推公式
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=2e5+10,mod=1e9+7;
#define PII pair<int,int>
void solve()
{
ll n;
cin>>n;
if(n==1){
cout<<0<<endl;return;
}
n=n-1;
ll ans=((n%mod)*(n%mod))%mod;
n=n+1;
ans=(ans*(((n%mod)*(n%mod))%mod))%mod;
ans=(ans*2)%mod;
cout<<ans<<endl;
}
int main()
{
int t;
cin >> t;
while (t--) solve();
}
1005
- 思路
可操作的方案数只存在于前几位相同的
- 代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
void solve() {
ll n,b=0,ans;
string s;
scanf("%lld",&n);
cin>>s;
for (ll i=1; i < s.size(); ++i) {
if (s[i] == s[0]) b++;
else break;
}
ans=qpow(2,b);
printf("%lld\n",ans);
}
int main() {
int t;
scanf("%d",&t);
while(t--) solve();
return 0;
}
1012
- 思路
简单题
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10,mod=1e9+7;
#define PII pair<int,int>
// #define x first
// #define y second
#define PB push_back
void solve()
{
string s;cin>>s;
if(s.find("114514")!=s.npos){
cout<<"AAAAAA"<<endl;
}
else
{
cout<<"Abuchulaile"<<endl;
}
}
int main()
{
// #ifndef ONLINE_JUDGE
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// #endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
solve();
}
1008
1011
第三场
1011
-
思路
线段树上代表区间长度相同的节点的子树点数相同,且最多只有 O ( l o g n ) O(log n) O(logn) 种本质不同的区
间长度,对区间长度记忆化搜索即可。
时间复杂度 O ( l o g n l o g l o g n ) O(log n log log n) O(lognloglogn)。 -
代码
#include<cstdio>
#include<map>
using namespace std;
typedef long long ll;
int Case;ll n,k;
map<ll,ll>T;
ll build(ll n){
if(T.find(n)!=T.end())return T[n];
if(n<=k)return T[n]=1;
return T[n]=build(n/2)+build(n-n/2)+1;
}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%lld%lld",&n,&k);
T.clear();
printf("%lld\n",build(n));
}
}
1004
- 思路
使用分母表示好像可以避开精度。
- 代码
#include<cstdio>
#include<algorithm>
using namespace std;
typedef pair<int,int>P;
const int N=100005;
int Case,n,i,j,k,f[N];
P a[N];
inline int abs(int x){return x>0?x:-x;}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d",&n);
for(i=1;i<=n;i++){
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
int dx=x2-x1,dy=y2-y1;
if(dx==0)dy=1;
else if(dy==0)dx=1;
else{
if(dx<0)dx=-dx,dy=-dy;
int d=gcd(abs(dx),abs(dy));
dx/=d,dy/=d;
}
a[i]=P(dx,dy);
}
sort(a+1,a+n+1);
for(i=1;i<=n;i++) f[i]=0;
for(i=1;i<=n;i=j){
for(j=i;j<=n&&a[i]==a[j];j++);
for(k=1;k<=j-i;k++) f[k]++;//每一层可以撑多少次
}
for(i=j=1;i<=n;i++){
while(!f[j])j++;
f[j]--;//撑一次减一。
printf("%d\n",i-j);
}
}
}
1007
- 思路
因为有了 m i n ( 255 , ) min(255,) min(255,) 的限制,所以最好还是 R G B RGB RGB 分开搞,可以直接格式化输出 16 16 16 进制
- 代码
#include<cstdio>
const int N=100005;
int Case,n,m,i,x,y,t[N],r[N],g[N],b[N],f[N];
inline int ask(int*s,int l,int r){
int x=f[r],ret;
if(x<l)ret=s[r]-s[l-1];
else ret=s[r]-s[x-1];
return ret<255?ret:255;
}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d%X",&t[i],&x);
b[i]=x&255;
x>>=8;
g[i]=x&255;
x>>=8;
r[i]=x;
r[i]+=r[i-1];
g[i]+=g[i-1];
b[i]+=b[i-1];
if(t[i]==1)f[i]=i;else f[i]=f[i-1];
}
while(m--){
scanf("%d%d",&x,&y);
printf("%02X%02X%02X\n",ask(r,x,y),ask(g,x,y),ask(b,x,y));
}
}
}
第四场
1001
- 思路
检查所有系数是否为 0 0 0 即可,啊这,一开始做复杂了。
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10,mod=1e9+7;
#define PII pair<int,int>
// #define x first
// #define y second
#define PB push_back
int n,m;
void solve()
{
string s;cin>>s;
vector<string> vec;
string ans="";
for(int i=0;i<s.size();i++){
if(s[i]=='+'){
if(ans.size())
vec.push_back(ans);
ans="";
}
else{
ans+=s[i];
}
}
if(ans.size()) vec.push_back(ans);
for(int i=0;i<vec.size();i++){
string ss=vec[i];
if(ss[0]=='0') continue;
else {
cout<<"NO"<<endl;return;
}
}
cout<<"YES"<<endl;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.txt", "r", stdin);
freopen("aout.txt", "w", stdout);
#endif
int q;cin>>q;
while(q--){
solve();
}
}
1009
- 思路
简单题,注意汉字有可能有两部分,从前面处理,然后再从后面处理即可。
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e3+10,mod=1e9+7;
#define PII pair<int,int>
// #define x first
// #define y second
#define PB push_back
char mp[N][N];
int cnt=0;
void solve()
{
cnt++;
for(int i=1;i<=30;i++){
for(int j=1;j<=100;j++)cin>>mp[i][j];
}
int p=100;int flag=1;
vector<int> vec;
cout<<"Case #"<<cnt<<":"<<endl;
for(int i=0;i<12;i++){
if(flag&1){
for(p;p>=1;p--){
bool falg=0;
for(int j=1;j<=30;j++){
if(mp[j][p]=='#'){
vec.push_back(p);p--;falg=1;break;
}
}
if(falg) break;
}
flag++;
}
else{
for(p;p>=1;p--){
bool falg=0;
for(int j=1;j<=30;j++){
if(mp[j][p]=='#'){
falg=1;
}
}
if(!falg) {
vec.push_back(p+1);p--;break;
}
}
flag++;
}
}
for(p;p>=1;p--){
bool falg=0;
for(int j=1;j<=30;j++){
if(mp[j][p]=='#'){
vec.push_back(p);falg=1;break;
}
}
if(falg) break;
}
for(int i=1;i;i++){
bool falg=0;
for(int j=1;j<=30;j++){
if(mp[j][i]=='#'){
vec.push_back(i);falg=1;break;
}
}
if(falg) break;
}
reverse(vec.begin(),vec.end());
// for(int i=0;i<14;i++){
// cout<<vec[i]<<endl;
// }
for(int i=0;i<7;i++){
cout<<vec[i*2]<<" "<<vec[i*2+1]<<endl;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.txt", "r", stdin);
freopen("aout.txt", "w", stdout);
#endif
int q;cin>>q;
while(q--){
solve();
}
}
1002
- 思路
直接
d
f
s
dfs
dfs 统计
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e3+10,mod=1e9+7;
#define PII pair<int,int>
// #define x first
// #define y second
#define PB push_back
int a[N][N];
int w[N];
int vis[N];
bool vis1[N];
vector<int> vec[N];
int root;
const ll mod1=1e9+7,mod2=1e9+9,xx=19560929;
ll x1[N],x2[N];
void init() {
x1[0]=1;
x2[0]=1;
for (int i=1; i <= 2000; ++i) x1[i]=(x1[i-1]*xx)%mod1;
for (int i=1; i <= 2000; ++i) x2[i]=(x2[i-1]*xx)%mod2;
}
void dfs(int x)
{
//cout<<"root:"<<x<<endl;
if(vis1[x]) return;
vis1[x]=1;
for(int i=0;i<vec[x].size();i++){
//cout<<vec[x][i]<<endl;
if(vis1[vec[x][i]]) continue;
//cout<<root<<endl;cout<<vec[x][i]<<endl;
if(!vis[w[vec[x][i]]]){
a[root][vec[x][i]]=a[root][x]+1;
}
else {
a[root][vec[x][i]]=a[root][x];
}
vis[w[vec[x][i]]]++;
dfs(vec[x][i]);
vis1[vec[x][i]]=1;
vis[w[vec[x][i]]]--;
}
}
void solve()
{
memset(vis,0,sizeof(vis));
memset(vis1,0,sizeof(vis1));
memset(a,0,sizeof(a));
int n;cin>>n;
for(int i=1;i<=n;i++){
vec[i].clear();
}
for(int i=2;i<=n;i++){
int xt;cin>>xt;
vec[xt].push_back(i);
vec[i].push_back(xt);
}
for(int i=1;i<=n;i++) cin>>w[i];
for(int i=1;i<=n;i++){
memset(vis,0,sizeof(vis));
memset(vis1,0,sizeof(vis1));
vis[w[i]]++;
root=i;a[root][root]=1;
dfs(root);
}
for(int i=1;i<=n;i++){
ll ans1=0,ans2=0;
for(int j=1;j<=n;j++){
ans1=(ans1+a[i][j]*x1[j-1])%mod1;
ans2=(ans2+a[i][j]*x2[j-1])%mod2;
}
cout<<ans1<<" "<<ans2<<endl;
}
}
int main()
{
init();
#ifndef ONLINE_JUDGE
freopen("a.txt", "r", stdin);
freopen("aout.txt", "w", stdout);
#endif
int q;cin>>q;
while(q--){
solve();
}
}
- 标程
// Correct solution in time complexity O(n^2)
// Method: DFS
// Author: HeRaNO
#include <cstdio>
#include <vector>
#define MAXN 2005
const int N = 2000;
const int b = 19560929;
const int M1 = 1000000007;
const int M2 = 1000000009;
int n, ans, c[MAXN], p[MAXN], cnt[MAXN], _1[MAXN], _2[MAXN];
std::vector <int> g[MAXN];
inline void init(int n)
{
_1[0] = _2[0] = 1;
for (int i = 1; i <= n; i++)
_1[i] = 1LL * _1[i - 1] * b % M1,
_2[i] = 1LL * _2[i - 1] * b % M2;
return ;
}
inline void fadd1(int &x, int y){ x += y; if (x >= M1) x -= M1; return ; }
inline void fadd2(int &x, int y){ x += y; if (x >= M2) x -= M2; return ; }
inline void add(int x)
{
if (!cnt[x]) ++ans;
++cnt[x]; return ;
}
inline void del(int x)
{
if (cnt[x] == 1) --ans;
--cnt[x]; return ;
}
inline void DFS(int x, int f)
{
add(c[x]); p[x] = ans;
for (auto v : g[x]) if (v != f) DFS(v, x);
del(c[x]);
return ;
}
inline void Solve()
{
scanf("%d", &n);
for (int i = 2, x; i <= n; i++)
{
scanf("%d", &x);
g[x].push_back(i); g[i].push_back(x);
}
for (int i = 1; i <= n; i++) scanf("%d", &c[i]);
for (int i = 1; i <= n; i++)
{
DFS(i, -1);
int h1 = 0, h2 = 0;
for (int j = 1; j <= n; j++)
{
fadd1(h1, 1LL * p[j] * _1[j - 1] % M1);
fadd2(h2, 1LL * p[j] * _2[j - 1] % M2);
}
printf("%d %d\n", h1, h2);
}
for (int i = 1; i <= n; i++)
g[i].clear();
return ;
}
int main()
{
int T;
init(N - 1);
scanf("%d", &T);
while (T--) Solve();
return 0;
}
1008
- 思路
线段树维护
- 代码
#include<bits/stdc++.h>
using namespace std;
#define ls (x<<1)
#define rs (x<<1|1)
const int N = 1e5 + 5;
const int inf = 0x3f3f3f3f;
vector<int> e[N];
int tr[2][N << 2], lz[2][N << 2];
void push_down(int f, int x, int l, int r, int mid) {
if (lz[f][x] == -1)return;
tr[f][ls] = lz[f][x] * (mid - l + 1);
tr[f][rs] = lz[f][x] * (r - mid);
lz[f][ls] = lz[f][rs] = lz[f][x];
lz[f][x] = -1;
}
//l,r代表的是该结点代表的区间;L,R代表的是更新的区间;v代表的是更新的值;x代表的是结点编号;
void update(int f,int x, int l, int r, int L, int R, int v) {
if (L <= l && R >= r) {
tr[f][x] = (r - l + 1) * v;
lz[f][x] = v;
return;
}
int mid = (l + r) >> 1;
push_down(f, x, l, r, mid);
if (R <= mid) update(f, ls, l, mid, L, R, v);
else if (L > mid) update(f, rs, mid + 1, r, L, R, v);
else {
update(f, ls, l, mid, L, mid, v);
update(f, rs, mid + 1, r, mid + 1, R, v);
}
tr[f][x] = tr[f][ls] + tr[f][rs];
}
//f记录行号;x表示结点;l,r表示结点的区间;L,R表示查询的区间。
int query(int f, int x, int l, int r, int L, int R) {
if (!tr[f][x])return inf;
if (l == r)return l;
int mid = l + r >> 1;
push_down(f, x, l, r, mid);
if (L <= l && R >= r) {
if (tr[f][ls] > 0) return query(f, ls, l, mid, l, mid);
else return query(f, rs, mid + 1, r, mid + 1, r);
}
else {
if (R <= mid)return query(f, ls, l, mid, L, R);
else if (L > mid)return query(f, rs, mid + 1, r, L, R);
else return min(query(f, ls, l, mid, L, mid), query(f, rs, mid + 1, r, mid + 1, R));
}
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
int n, m, k;
scanf("%d %d %d", &n, &m, &k);
for (int i = 1; i <= n; ++i) e[i].clear();
for (int i = 1; i <= (m << 2); ++i) {
tr[0][i] = tr[1][i] = 0;
lz[0][i] = lz[1][i] = -1;
}
for (int i = 0; i < k; ++i) {
int x, y;
scanf("%d %d", &x, &y);
e[x].push_back(y);
}
long long ans = 0;
update(0, 1, 1, m, 1, 1, 1);
for (int x = 1; x <= n; ++x) {
int l = 0;
sort(e[x].begin(), e[x].end());
for (auto& y : e[x]) {
if (y - 1 >= l + 1) {
int pos = query((x & 1) ^ 1, 1, 1, m, l + 1, y - 1);
if (pos != inf) update(x & 1, 1, 1, m, pos, y - 1, 1);
}
l = y;
}
if (l + 1 <= m) {
int pos = query((x & 1) ^ 1, 1, 1, m, l + 1, m);
if (pos != inf) update(x & 1, 1, 1, m, pos, m, 1);
}
ans += tr[x & 1][1];//
update((x & 1) ^ 1, 1, 1, m, 1, m, 0);//把上一行全部清零,用于下一行计算。
}
printf("%lld\n", ans);
}
return 0;
}
第五场
1003
- 思路
小雨哥,yyds
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10,mod=1e9+7;
#define PII pair<int,int>
#define x first
#define y second
#define PB push_back
void solve()
{
ll n,k;
cin>>n>>k;
if(n-k<2){
cout<<"Yes"<<endl;
}
else{
cout<<"No"<<endl;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.txt", "r", stdin);
freopen("aout.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
solve();
}
1006
- 思路
直接模拟
- 代码
#include<cstdio>
#include<map>
using namespace std;
typedef long long ll;
int Case;int n,k;
map<ll,ll>T;
// ll build(ll n){
// if(T.find(n)!=T.end())return T[n];
// if(n<=2)return T[n]=n;
// return T[n]=2*build((n-1)/3)+build(n-(n-1)/3*2)+1;
// }
ll tot=0;
void build(int l,int r)
{
tot++;
if(l==r) return;
if(l+1==r){
build(l,l);
build(r,r);
}
else{
int x=(r-l)/3;
if((r-l)%3) x++;
int b=x+l-1;
int c=(b+r)/2;
build(l,b);build(b+1,c);build(c+1,r);
}
}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d",&n);
tot=0;
for(int i=1;i<=n;i++){
int x;scanf("%d",&x);
}
build(1,n);
// T.clear();
printf("%lld\n",tot);
}
}
1007
- 思路
第一层铺满,上面的 L L L 型铺
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef double db;
const int P=1e9+7;
ll n,ret1,ret2,ret3,q;
int T;
ll Pow(ll x,ll k) {
ll ret=1;
for (; k; k>>=1,x=x*x%P) if (k&1) ret=ret*x%P;
return ret;
}
int main()
{
scanf("%d",&T);
while (T--) {
scanf("%lld",&n),n%=P;
ret1=n*n%P*(n+1)%P*(n+1)%P*(1+2*n)%P*Pow(12,P-2)%P*n%P*n%P;
ret2=(n*n)%P*((n+1)*(n+1)%P)%P*(n*2+1)%P*Pow(12,P-2)%P;
ret3=((((n+1)*n)%P*Pow(2,P-2)%P+n*(n+1)%P*(n*2+1)%P*Pow(6,P-2)%P-2+P)%P)*(((n+1)*n%P*Pow(2,P-2)%P-1+P)%P)%P;
printf("%lld\n",(ret3+ret2)%P);
printf("%lld\n",ret1%P);
}
return 0;
}
第六场
1001
- 思路
负数,就变成正数之后往后走,然后正数往后走,如果不可能,加上负数往后走。所以就不可能出现-1的情况;因为连续的大于两个数相加一定不可能是素数,所以要么这一位是素数,要么这连续两个是素数。
- 代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e7+1;//这个是在哪一个范围内
int prime[maxn];
int visit[maxn];//1代表是偶数,0代表是奇数
void Prime()
{
visit[0]=1;
visit[1]=1;
for (int i = 2;i <= maxn; i++)
{
if (!visit[i])
{
prime[++prime[0]] = i;
}
for (int j = 1; j <=prime[0] && i*prime[j] <= maxn; j++)
{
visit[i*prime[j]] = 1;
if (i % prime[j] == 0)
{
break;
}
}
}
}
void solve()
{
int x;cin>>x;
if(x>1 &&! visit[x]){
cout<<1<<endl;
}
else if(x<0){
int tt=-x+1;
if(!visit[tt]){
cout<<(-x)*2+1+1<<endl;
}
else{
if(!visit[tt*2+1]){
cout<<2+(-x)*2+1<<endl;
}
else{
int tt=-x+2;
for(int i=tt;i;i++){
if(!visit[i]){
cout<<2*i<<endl;break;
}
if(!visit[i*2+1]){
cout<<2*i+1<<endl;break;
}
}
}
}
}
else if(x==0){
cout<<3<<endl;
}
else if(x==1){
cout<<2<<endl;
}
else{
if(!visit[2*x-1]||!visit[2*x+1]){
cout<<2<<endl;
}
else{
int tt=x+1;
for(int i=tt;i;i++){
if(!visit[i]){
cout<<2*i<<endl;break;
}
if(!visit[i*2+1]){
cout<<2*i+1<<endl;break;
}
}
}
}
}
int main()
{
Prime();
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t;cin>>t;
while(t--){
solve();
}
}
1005
- 思路
]
- 代码
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while (T--) {
int n, m;
cin >> n >> m;
vector<int> f(n + 2);
f[n + 1] = 1;
while (m--) {
int v;
cin >> v;
f[v] = 1;
}
vector<pair<int, int>> size;
int have = 0;
int count = 0;
for (int i = 1; i <= n + 1; i++) {
if (f[i]) {
if (have) {
size.push_back(make_pair(have, count));
}
have = 0;
count += 1;
} else {
have += 1;
}
}
sort(size.begin(), size.end());
if (size.empty()) {
cout << "YES\n";
continue;
}
int sum = 0;
for (auto s: size) {
sum += s.first;
}
if (size.back().first <= sum - size.back().first + size.back().second) {
cout << "YES\n";
} else {
cout << "NO\n";
}
}
return 0;
}
第七场
1001
- 思路
啊这,直接判断大小,搞的乱七八糟的
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10,mod=1e9+7;
#define PII pair<int,int>
#define x first
#define y second
#define PB push_back
void solve()
{
double p,q;
cin>>p>>q;
if(p>q){
cout<<"ENJ0Y YOURS3LF!"<<endl;
}
else{
cout<<"N0 M0R3 BL4CK 1CE TEA!"<<endl;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("b.txt", "r", stdin);
freopen("bout.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
solve();
}
1003
- 思路
推个公式
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;const ll mod=1e9+7;
#define PII pair<int,int>
#define x first
#define y second
#define PB push_back
double Pow[N];
void init()
{
Pow[0]=1.0;
for(int i=1;i<N;i++){
Pow[i]=Pow[i-1]*2.0;
}
}
void solve()
{
int k;scanf("%d",&k);k--;
double xroot,yroot,xl,yl,xr,yr;
scanf("%lf %lf %lf %lf %lf %lf",&xroot,&yroot,&xl,&yl,&xr,&yr);
double h=(yroot-yl),d=(xr-xl);
double ans=(h*d)/2;
k--;
double anst=(2*k-1)*2+3/Pow[k];
ans*=anst;
printf("%.3lf\n",ans);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.txt", "r", stdin);
freopen("aout.txt", "w", stdout);
#endif
init();
int t;
scanf("%d",&t);
while (t--)
solve();
}
1012
- 思路
将每个字母按块考虑,然后推出按位贡献公式,或者按照标程维护差分。
- 代码
typedef long long ll;
typedef pair<int, int> P;
ll mod = 998244353;
struct Recorder{
ll summ = 0;
ll now = 0;
};
map<char, Recorder> record;
const string alphas = "abcdefghijklmnopqrstuvwxyz";
char s[1000002];
void solve(){
scanf("%s",s);
record.clear();
int n = strlen(s);
ll ans = 0;
ll sum=0;
for(int i=1;i<=n;i++){
char c = s[i - 1];
sum = (sum + record[c].summ + i)%mod;
record[c].summ = (record[c].summ + i * 2) % mod;
ans = (ans + sum) % mod;
}
printf("%lld\n",ans%mod);
}
int main(){
//_fast_;
int t; scanf("%d",&t); while (t--)
solve();
}
- 标程
#include<bits/stdc++.h>
using namespace std;
const int P = 998244353;
int n;
char ch[200005];
int solve(vector<int> vec){
vec.push_back(n+1);
int ans=0,per=0,dif=0;
for (int i=1;i<vec.size();i++){
ans=(1ll*ans+1ll*per*(vec[i]-vec[i-1]))%P;
dif=(1ll*dif+2ll*vec[i-1]+vec[i]-vec[i-1])%P;
per=(per+dif)%P;
}
return ans;
}
void solve(){
scanf("%s",ch+1);
n=strlen(ch+1);
ch[n+1]='\0';
vector<int> a[28];
for (int i=0;i<=25;i++) a[i].push_back(0);
for (int i=1;i<=n;i++) {
a[ch[i]-'a'].push_back(i);
}
int ans=0;
for (int i=0;i<=25;i++) {
ans=(ans+solve(a[i]))%P;
}
printf("%d\n",ans);
}
int main(){
int t;
scanf("%d",&t);
while (t--) solve();
}
1004
- 思路
将式子展开可以得到:
C
m
+
n
−
1
n
−
1
+
C
m
+
n
−
2
n
−
1
+
⋯
+
C
m
n
−
1
+
C
m
−
1
n
−
1
C_{m+n-1}^{n-1}+C_{m+n-2}^{n-1}+\dots+C_{m}^{n-1}+C_{m-1}^{n-1}
Cm+n−1n−1+Cm+n−2n−1+⋯+Cmn−1+Cm−1n−1
根据组合数性质:
C
m
n
=
C
m
−
1
n
−
1
+
C
m
−
1
n
C_m^n=C_{m-1}^{n-1}+C_{m-1}^{n}
Cmn=Cm−1n−1+Cm−1n
C
m
−
1
n
−
1
=
C
m
n
−
C
m
−
1
n
C
m
n
−
1
+
C
m
−
1
n
−
1
=
C
m
n
−
1
+
C
m
n
−
C
m
−
1
n
=
C
m
+
1
n
−
C
m
−
1
n
C
m
+
1
n
−
1
+
C
m
n
−
1
+
C
m
−
1
n
−
1
=
C
m
+
1
n
−
1
+
C
m
+
1
n
−
C
m
−
1
n
=
C
m
+
2
n
−
C
m
−
1
n
…
C
m
+
n
−
1
n
−
1
+
C
m
+
n
−
2
n
−
1
+
⋯
+
C
m
n
−
1
+
C
m
−
1
n
−
1
=
C
m
+
n
n
−
C
m
−
1
n
C_{m-1}^{n-1}=C_{m}^n-C_{m-1}^n\\ C_{m}^{n-1}+C_{m-1}^{n-1}=C_m^{n-1}+C_m^n-C_{m-1}^{n}=C_{m+1}^n-C_{m-1}^n\\ C_{m+1}^{n-1}+C_{m}^{n-1}+C_{m-1}^{n-1}=C_{m+1}^{n-1}+C_{m+1}^n-C_{m-1}^n=C_{m+2}^{n}-C_{m-1}^n\\ \dots \\ C_{m+n-1}^{n-1}+C_{m+n-2}^{n-1}+\dots+C_{m}^{n-1}+C_{m-1}^{n-1}=C_{m+n}^{n}-C_{m-1}^n
Cm−1n−1=Cmn−Cm−1nCmn−1+Cm−1n−1=Cmn−1+Cmn−Cm−1n=Cm+1n−Cm−1nCm+1n−1+Cmn−1+Cm−1n−1=Cm+1n−1+Cm+1n−Cm−1n=Cm+2n−Cm−1n…Cm+n−1n−1+Cm+n−2n−1+⋯+Cmn−1+Cm−1n−1=Cm+nn−Cm−1n
- 代码
#include <stdio.h>
#define MN 2000000
typedef long long ll;
const int mod = 1000000007;
int fac[MN+5],inv[MN+5];
ll qpow(ll bsc,ll y){
ll ret = 1;
while(y){
if(y&1) ret = ret*bsc%mod;
bsc = bsc*bsc%mod;
y >>= 1;
}
return ret;
}
void init(){
fac[0] = 1;
for(int i=1;i<=MN;i++)
fac[i] = (ll)fac[i-1]*i%mod;
inv[MN] = qpow(fac[MN],mod-2);
for(int i=MN-1;i>=0;i--)
inv[i] = (ll)inv[i+1]*(i+1)%mod;
}
int C(int n,int m){
if(m>n) return 0;
return (ll)fac[n]*inv[m]%mod*inv[n-m]%mod;
}
void solve(){
int n,m;
scanf("%d%d",&n,&m);
int ans = C(m+n,n)-C(m-1,n);
if(ans<0) ans += mod;
printf("%d\n",ans);
}
int main(){
init();
int T;
scanf("%d",&T);
while(T--) solve();
}
1008
- 思路
直接模拟就行呀,标程确实写的妙呀!
将原本的八种情况抽象成了四种。
- 标程
#include<bits/stdc++.h>
using std::max;
struct note{
int x,y;
friend note operator + (note a1,note a2){
return {a1.x+a2.x,a1.y+a2.y};
}
friend note operator - (note a1,note a2){
return {a1.x-a2.x,a1.y-a2.y};
}
}list[200005],rt;
int curdir,n,cnt;
char do_list[2000005];
void get_to_do_list(note tar)
{
note vec=tar-rt;
int disf=0,disb=0,disr=0,disl=0;
if (vec.x>0) {
if (curdir==0) disr=vec.x;
if (curdir==1) disf=vec.x;
if (curdir==2) disl=vec.x;
if (curdir==3) disb=vec.x;
}else{
if (curdir==0) disl=-vec.x;
if (curdir==1) disb=-vec.x;
if (curdir==2) disr=-vec.x;
if (curdir==3) disf=-vec.x;
}
if (vec.y>0) {
if (curdir==0) disf=vec.y;
if (curdir==1) disl=vec.y;
if (curdir==2) disb=vec.y;
if (curdir==3) disr=vec.y;
}else{
if (curdir==0) disb=-vec.y;
if (curdir==1) disr=-vec.y;
if (curdir==2) disf=-vec.y;
if (curdir==3) disl=-vec.y;
}
if (disf) {
for (int i=1;i<=disf;i++) do_list[++cnt]='f';
if (disr) {
do_list[++cnt]='c';
curdir=(curdir+1)%4;
for (int i=1;i<=disr;i++) do_list[++cnt]='f';
}else{
do_list[++cnt]='u';
curdir=(curdir-1+4)%4;
for (int i=1;i<=disl;i++) do_list[++cnt]='f';
}
}else{
if (disr) {
do_list[++cnt]='c';
curdir=(curdir+1)%4;
for (int i=1;i<=disr;i++) do_list[++cnt]='f';
do_list[++cnt]='c';
curdir=(curdir+1)%4;
for (int i=1;i<=disb;i++) do_list[++cnt]='f';
}else{
do_list[++cnt]='u';
curdir=(curdir-1+4)%4;
for (int i=1;i<=disl;i++) do_list[++cnt]='f';
do_list[++cnt]='u';
curdir=(curdir-1+4)%4;
for (int i=1;i<=disb;i++) do_list[++cnt]='f';
}
}
}
void solve(){
for (int i=0;i<=cnt+1;i++) do_list[i]='\0';
cnt=0;
scanf("%d%d%d",&rt.x,&rt.y,&curdir);
scanf("%d",&n);
for (int i=1;i<=n;i++) {
scanf("%d%d",&list[i].x,&list[i].y);
}
for (int i=1;i<=n;i++) {
get_to_do_list(list[i]);
rt=list[i];
}
puts(do_list+1);
}
int main()
{
int t;
scanf("%d",&t);
while (t--) solve();
}
1007
- 思路
连边找环,处理环.
拓扑排序把不在环里的处理掉首先。
- 代码
#include <stdio.h>
#include <queue>
#define MN 100000
typedef long long ll;
int n,a[MN+5],din[MN+5];
void solve(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
din[i] = 0;
}
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
din[a[i]]++;
}
std::queue<int> Q;
for(int i=1;i<=n;i++){
if(din[i]==0) Q.push(i);
}
while(!Q.empty()){
int u = Q.front();
Q.pop();
din[a[u]]--;
if(din[a[u]]==0){
Q.push(a[u]);
}
}
ll p=-1,q=-1;
for(int i=1;i<=n;i++){
if(din[i]==0) continue;
ll tp=0,tq=0;
for(;din[i];i=a[i]){
tp += i;
tq ++;
din[i] = 0;
}
if(p==-1){
p = tp;
q = tq;
}else{
if(p*tq!=q*tp){
puts("NO");
return;
}
}
}
puts("YES");
return;
}
int main(){
int T;
scanf("%d",&T);
while(T--) solve();
}
1006
- 思路
]
- 代码
#include<bits/stdc++.h>
using namespace std;
const int g = 10;
const int P = 1000000007;
int ksm(int b,int k){
int ans=1;
while (k) {
if (k&1) ans=1ll*ans*b%P;
b=1ll*b*b%P;
k>>=1;
}
return ans;
}
int solve(){
int t,v,R;
scanf("%d%d%d",&t,&v,&R);
if (4ll*g*t*t*t*v+4ll*v*v*t*t+1ll*g*g*t*t*t*t-4ll*R*R<=0) {
return 0;
}
if (4ll*g*t*t*t*v+4ll*v*v*t*t+1ll*g*g*t*t*t*t-4ll*R*R>=8ll*g*t*t*t*v) {
return 1;
}
return 1ll*(4ll*g*t*t*t*v+4ll*v*v*t*t+1ll*g*g*t*t*t*t-4ll*R*R)*ksm(8ll*g*t*t*t*v%P,P-2)%P;
}
int main()
{
int t;
scanf("%d",&t);
while (t--)
printf("%d\n",solve());
}
第八场
1003
- 思路
最小生成树的最大权值边
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e3+10,mod=1e9+7;
#define PII pair<int,int>
#define x first
#define y second
#define PB push_back
PII a[N];
ll mp[N][N];
ll d[N];int n;
bool v[N];
void prim() {
memset(d, 0x3f, sizeof(d));
memset(v, 0, sizeof(v));
d[1] = 0;
for (int i = 1; i < n; i++) {
int x = 0;
for (int j = 1; j <= n; j++)
if (!v[j] && (x == 0 || d[j] < d[x])) x = j;
v[x] = 1;
for (int y = 1; y <= n; y++)
if (!v[y]) d[y] = min(d[y],mp[x][y]);
}
}
void solve()
{
// map<PII,int> mp;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].x>>a[i].y;
}
memset(mp,0x3f3f3f3f,sizeof(mp));
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
ll tx=abs(a[i].x-a[j].x),ty=abs(a[i].y-a[j].y);
mp[i][j]=(tx*tx)+ty*ty;
mp[j][i]=mp[i][j];
}
}
prim();
ll ans=0;
for(int i=1;i<=n;i++){
ans=max(ans,d[i]);
}
cout<<ans<<endl;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("b.txt", "r", stdin);
freopen("bout.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// cout<<ll(5*1e18)<<endl;
int t;
cin >> t;
while (t--)
solve();
}
1006
- 思路
nim博弈,每个数字转化成有多少个质因数
- 代码
#include<bits/stdc++.h>
using namespace std;
int num[10000010];
int prm[10000010],cnt;
bool f[10000010];
int t,n;
int main()
{
for(int i=2;i<=10000000;i++)
{
if(!f[i])prm[++cnt]=i,num[i]=1;
for(int j=1;j<=cnt && i*prm[j]<=10000000;j++)
{
f[i*prm[j]]=true;
num[i*prm[j]]=num[i]+1;//i * prm[j]这个数只被prm[j]筛过一次,因为欧拉筛只会被最小值质因数筛一次,所以就等于num[i]+1;
if(i%prm[j]==0)break;
}
}//欧拉筛质因数个数
scanf("%d",&t);
while(t--)
{
int ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
ans^=num[x];
}
if(ans)puts("Alice");else puts("Bob");
}
return 0;
}
1009
- 思路
AC 自动机,字符串 Hash,字典树都可以;只不过后面两种卡常
- AC 自动机代码
#include<bits/stdc++.h>
using namespace std;
queue<int>q;
bool word[601000];
int child[601000][26],fail[601000],Size,pos[101000];
int cnta[601000],cntb[601000],posn[601000],lens[601000];
void Insert(char S[],int id)
{
int len=strlen(S);
int now=0;
for(int i=0;i<len;++i)
{
if(!child[now][S[i]-'a'])
child[now][S[i]-'a']=Size++;
now=child[now][S[i]-'a'];
}
word[now]=1;
lens[now]=len;
pos[id]=now;
}
void build()
{
fail[0]=-1;
q.push(0);
while(!q.empty())
{
int U=q.front(); q.pop();
for(int i=0;i<26;++i)
if(child[U][i])
{
int V=fail[U];
while(V!=-1)
{
if(child[V][i])
{
fail[child[U][i]]=child[V][i];
break;
}
V=fail[V];
}
if(V==-1)
fail[child[U][i]]=0;
if(word[fail[child[U][i]]])
word[child[U][i]]=1;
q.push(child[U][i]);
}
}
}
void match(char S[])
{
int len=strlen(S);
int res=0,now=0;
for(int i=0;i<len;++i)
{
if(child[now][S[i]-'a'])
now=child[now][S[i]-'a'];
else
{
int U=fail[now];
while(U!=-1 && child[U][S[i]-'a']==0)
U=fail[U];
if(U==-1)
now=0;
else
now=child[U][S[i]-'a'];
}
if(!word[now])
continue;
int U=now;
while(U)
{
if(word[U])
{
++cnta[U];
if(posn[U]<=i-lens[U])
{
++cntb[U];
posn[U]=i;
}
}
U=fail[U];
}
}
}
void Init()
{
memset(child,0,sizeof(child));
memset(fail,0,sizeof(fail));
memset(word,0,sizeof(word));
memset(pos,0,sizeof(pos));
memset(cnta,0,sizeof(cnta));
memset(cntb,0,sizeof(cntb));
memset(posn,-1,sizeof(posn));
memset(lens,0,sizeof(lens));
Size=1;
}
char s[101000];
bool op[101000];
int n;
int main()
{
char ss[9];
int T=0;
int t;std::cin>>t;
//freopen("zoj3228.in","r",stdin);
while(t--)
{cin>>s;
cin>>n;
Init();
for(int i=1;i<=n;++i)
{
scanf("%s",ss);
Insert(ss,i);
}
build();
match(s);
for(int i=1;i<=n;++i)
cout<<cntb[pos[i]]<<endl;
}
return 0;
}
- 字符串 Hash 代码
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
const int N=1e6+10,M=13331;
template<typename T>
void Debug(T x,string s){
cout<<s<<": "<<x<<endl;
}
int n;
ULL p[N],h[N];
ULL h_s[N];
char ts[N],s[N];
void init()
{
p[0]=1;
for(int i=1;i<=N;i++)
p[i]=p[i-1]*M;
}
void Hash(char *str)
{
// cout<<str<<endl;
p[0]=1;
for(int i=1;i<=n;i++)
{
h[i]=h[i-1]*M+str[i-1];
}
}
ULL get(int l,int r)
{
return h[r]-h[l-1]*p[r-l+1];
}
int m;
void Hash_1(char *str)
{
// cout<<str<<endl;
for(int i=1;i<=m;i++)
{
h_s[i]=h_s[i-1]*M+str[i-1];
// cout<<str[i]<<" \n"[i==m];
}
}
ULL get_1(int l,int r)
{
return h_s[r]-h_s[l-1]*p[r-l+1];
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.txt","r",stdin);
freopen("aout.txt","w",stdout);
#endif
int t;scanf("%d",&t);
// Debug(t,"t");
init();
getchar();
while(t--){
scanf("%s",s+1);
m=strlen(s+1);
int q;scanf("%d",&q);
Hash_1(s+1);
unordered_map<ULL,int> ans;
unordered_map<ULL,int> vis;
unordered_map<int,int> vis_len;
vector<ULL> vec;
for(int i=1;i<=q;i++){
scanf("%s",ts+1);
n=strlen(ts+1);
Hash(ts+1);
ULL ts_value=get(1,n);
// Debug(ts_value,"ts_value");
vec.push_back(ts_value);
vis_len[n]=1;
// printf("%d\n",cnt);
}
for(int i=1;i<=30;i++){
if(!vis_len[i]) continue;
for(int j=1;j+i-1<=m;j++){
// Debug(i,"i");Debug(j,"j");
if(vis[get_1(j,j+i-1)]&&j-vis[get_1(j,j+i-1)]<i){
continue;
}
ans[get_1(j,j+i-1)]++;
vis[get_1(j,j+i-1)]=j;
// Debug(j,"j");Debug(get_1(j,j+i-1),"get_1");
}
}
for(int i=1;i<=q;i++){
printf("%d\n",ans[vec[i-1]]);
}
}
}
- 标程
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int read() {
int tot = 0, fh = 1;
char c = getchar();
while ((c < '0') || (c > '9')) {
if (c == '-')
fh = -1;
c = getchar();
}
while ((c >= '0') && (c <= '9')) {
tot = tot * 10 + c - '0';
c = getchar();
}
return tot * fh;
}
const int maxn = 100010;
const int maxq = 30;
int T, opt, n, thi, len;
char s[maxn], a[maxn];
struct Trie {
int son[maxn * 30][26], las[maxn * 30], fla[maxn * 30], r;
void clear() {
memset(son, 0, sizeof(son));
memset(fla, 0, sizeof(fla));
memset(las, 0, sizeof(las));
r = 1;
}
int add(int thi, char x) {
if (son[thi][x] == 0) {
r++;
son[thi][x] = r;
}
return son[thi][x];
}
} tre;
int main() {
freopen("std.in","r",stdin);
freopen("std.out","w",stdout);
T = read();
for (opt = 1; opt <= T; opt++) {
scanf("%s", s);
len = strlen(s);
tre.clear();
for (int j = 0; j < len; j++) {
thi = 1;
for (int k = 0; k < min(len - j, maxq); k++) {
thi = tre.add(thi, s[j + k] - 'a');
if (tre.las[thi] <= j) {
tre.las[thi] = j + k + 1;
tre.fla[thi]++;
}
}
}
n = read();
for (int i = 1; i <= n; i++) {
scanf("%s", a);
thi = 1;
len = strlen(a);
for (int j = 0; j < len; j++) {
thi = tre.add(thi, a[j] - 'a');
}
printf("%d\n", tre.fla[thi]);
}
}
return 0;
}
- 注
无论是字典树还是 Hash 可能有AC自动机(不会),都会牵扯到一个不重复的问题,记录上次匹配的位置。
1008
- 思路
两个圆求相交面积,注意特判。
可以发现要使正方形卡片有可能被一个圆完全包含,它的中心轨迹一定是一个圆,所以本题就转化为了
计算两圆相交面积与第一个圆面积的比值。但其中还有一些细节,比如数据中奖励区域不一定能完全包
含卡片,以及两圆位置的不同情况要分类讨论,具体细节可以看代码。
- 代码
typedef long long ll;
typedef pair<int, int> P;
class Circle{
public:
double r;
double x;
double y;
Circle(){};
};
const double pi = 3.14159265358970323;
double area(Circle a, Circle b){
double r1 = a.r;
double r2 = b.r;
double d = sqrt((a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));
if (d >= r1+r2)
return 0;
if (r1 > r2){
double tmp = r1;
r1 = r2;
r2 = tmp;
}
if(r2 - r1 >= d) return pi*r1*r1;
double ang1 = acos((r1*r1+d*d-r2*r2)/(2*r1*d));
double ang2 = acos((r2*r2+d*d-r1*r1)/(2*r2*d));
return ang1*r1*r1 + ang2*r2*r2 - r1*d*sin(ang1);
}
Circle A, B, C, D;
double a;
double round(double number, unsigned int bits) {
ll integerPart = number;
number -= integerPart;
for (unsigned int i = 0; i < bits; ++i)
number *= 10;
number = (ll) (number + 0.5);
for (unsigned int i = 0; i < bits; ++i)
number /= 10;
return integerPart + number;
}
void solve(){
cin >> A.r >> A.x >> A.y;
cin >> B.r >> B.x >> B.y;
cin >> a;
double aa = a / 2;
double x1 = sqrt(A.r * A.r - aa * aa);
double r1 = x1 - aa;
double x2 = sqrt(B.r * B.r - aa * aa);
double r2 = max(0.0,x2 - aa);
//第二个有可能不成立。
// if(sqrt(2.0)*r2<a)
// {
// puts("0.000000");
// continue;
// }
//小于根号二。
C.x = A.x, C.y = A.y, C.r = r1;
D.x = B.x, D.y = B.y, D.r = r2;
double ans = area(C, D) / (pi * r1* r1);
printf("%.6f\n", ans);
}
int main(){
_fast_;
int t; cin >> t; while (t--)
solve();
}
1004
- 思路
- 标程
#include<bits/stdc++.h>
#define ll long long
#define maxn 100005
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
const ll mod=998244353;
ll a1[maxn],a2[maxn];
int T,n,q;
ll s1[maxn<<2],s2[maxn<<2],la[maxn<<2],tg[maxn<<2];
//s1,s2,la是区间修改的那个标记,tg是是否全部为0的标记。
ll lowbit(ll x)
{
return x&(-x);
}
void pushup(int rt)
{
s1[rt]=(s1[ls]+s1[rs])%mod;
s2[rt]=(s2[ls]+s2[rs])%mod;
tg[rt]=tg[ls]&tg[rs];
}
void pushdown(int rt)
{
la[ls]=la[ls]*la[rt]%mod;
la[rs]=la[rs]*la[rt]%mod;
s1[ls]=s1[ls]*la[rt]%mod;
s1[rs]=s1[rs]*la[rt]%mod;
tg[ls]|=tg[rt];
tg[rs]|=tg[rt];
if(tg[ls]) s2[ls]=0;
if(tg[rs]) s2[rs]=0;
la[rt]=1;
}
void build(int rt,int l,int r)
{
la[rt]=1,tg[rt]=0;
if(l==r){
s1[rt]=a1[l],s2[rt]=a2[l];
return;
}
int mid=l+r>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(rt);
}
ll query(int rt,int l,int r,int rl,int rr)
{
if(rl<=l&&rr>=r){
return (s1[rt]+s2[rt])%mod;
}
pushdown(rt);
int mid=l+r>>1;
ll ans=0;
if(rl<=mid)
ans+=query(ls,l,mid,rl,rr);
if(rr>mid)
ans+=query(rs,mid+1,r,rl,rr);
ans%=mod;
return ans;
}
void upd1(int rt,int l,int r,int rl,int rr)
{
if(l==r){
if(s2[rt])
s2[rt]-=lowbit(s2[rt]);
else{
s1[rt]=0;
tg[rt]=1;
}
return;
}
pushdown(rt);
int mid=l+r>>1;
if(rl<=mid&&!tg[ls])
upd1(ls,l,mid,rl,rr);
if(rr>mid&&!tg[rs])
upd1(rs,mid+1,r,rl,rr);
pushup(rt);
}
void upd2(int rt,int l,int r,int rl,int rr)
{
if(rl<=l&&rr>=r){
s1[rt]=s1[rt]*2%mod;
la[rt]=la[rt]*2%mod;
return;
}
pushdown(rt);
int mid=l+r>>1;
if(rl<=mid) upd2(ls,l,mid,rl,rr);
if(rr>mid) upd2(rs,mid+1,r,rl,rr);
pushup(rt);
}
int main()
{
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
ll x;
scanf("%lld",&x);
for(int k=30;k>=0;k--){
if((1ll<<k)<=x){
a1[i]=1ll<<k;
a2[i]=x-a1[i];
break;//最高位分开维护
}
}
}
build(1,1,n);
scanf("%d",&q);
for(int i=1;i<=q;i++){
int opt,l,r;
scanf("%d%d%d",&opt,&l,&r);
if(opt==1){
ll ans=query(1,1,n,l,r);
printf("%lld\n",ans);
}
else if(opt==2)
upd1(1,1,n,l,r);
else
upd2(1,1,n,l,r);
}
}
}
第十场
1004
- 思路
容斥
- 代码
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i < _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
using namespace std;
int bp[105], p[105], p0;
void build_p(int n) {
fo(i, 2, n) {
if(!bp[i]) p[++ p0] = i;
fo(j, 2, n / i) bp[i * j] = 1;
}
}
#define ull unsigned long long
int T; ull n;
int k;
ull ans;
const int M = (1 << 8) + 5;
struct nod {
ull a[M], b[M];
int a0, b0;
} a[17];
void dg(int x, ull y, int xs) {
if(x > k) {
if(xs == 1) {
a[k].a[++ a[k].a0] = y;
} else {
a[k].b[++ a[k].b0] = y;
}
return;
}
dg(x + 1, y * p[x], -xs);
dg(x + 1, y, xs);
}
const int m = 9699690;
const int fm = 1658880;
int f[m + 5];
void build() {
for(k = 1; k <= 16; k ++) {
if(k <= 8) {
dg(1, 1, 1);
} else {
dg(9, 1, 1);
}
}
fo(j, 1, 8) for(int i = p[j]; i <= m; i += p[j])
f[i] = 1;
fo(i, 1, m) f[i] = (!f[i]) + f[i - 1];
}
int main() {
// freopen("a.in", "r", stdin);
// freopen("a.out", "w", stdout);
build_p(100);
build();
for(scanf("%d", &T); T; T --) {
scanf("%llu %d", &n, &k);
ans = 0;
if(k <= 8) {
fo(i, 1, a[k].a0) {
ans += n / a[k].a[i];
}
fo(i, 1, a[k].b0) {
ans -= n / a[k].b[i];
}
} else {
fo(i, 1, a[k].a0) {
ull t = n / a[k].a[i];
ans += ((t / m) * fm + f[t % m]);
}
fo(i, 1, a[k].b0) {
ull t = n / a[k].b[i];
ans -= ((t / m) * fm + f[t % m]);
}
}
pp("%llu\n", ans);
}
}
第九场
1003
- 思路
尽量好,尽量坏,挑出在“一定”能在他前面的。
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10,mod=1e9+7;
template<typename T>
void Debug(T x,string s){
cout<<s<<": "<<x<<endl;
}
struct node
{
ll value,id;
}a[N];
ll b[N];
bool cmp(node a,node b)
{
return a.value>b.value;
}
#define PII pair<int,int>
#define x first
#define y second
#define PB push_back
void solve()
{
int n; cin>>n;
vector<int> hao(n+1),cha(n+1);
for(int i=1;i<=n;i++){
cin>>a[i].value;a[i].id=i;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++){
cin>>b[i];
}
// ll maxx_b=b[1];
// reverse(b+1,b+1+n);
for(int i=1;i<=n;i++){
int hao_cnt=0,cha_cnt=0,hao_p=n,cha_p=1;
ll hao_sum=b[1]+a[i].value,cha_sum=a[i].value+b[n];
for(int j=1;j<=n;j++){
if(i==j) continue;
if(hao_sum<=a[j].value){
hao_cnt++;
}
else{
if (a[j].value + b[hao_p] <= hao_sum) hao_p--;
else hao_cnt++;
}
}
for(int j=n;j>=1;j--){
if(i==j) continue;
if(cha_sum<=a[j].value){
cha_cnt++;
}
else{
if (a[j].value + b[cha_p] > cha_sum) {
cha_p++;
cha_cnt++;
}
}
}
hao[a[i].id]=hao_cnt+1;
cha[a[i].id]=cha_cnt+1;
}
for (int i=1; i <= n; ++i) cout<<hao[i]<<" "<<cha[i]<<endl;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.txt", "r", stdin);
freopen("aout.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
solve();
}
- 标程
#include<bits/stdc++.h>
#define F first
#define S second
using namespace std;
typedef pair<int,int>pi;
pi a[5005];
int b[5005],n,p,ans_best[5005],ans_worst[5005];
bool check1(int x,int y){
int p=n;
for (int i=n-y+1;i<=n;i++){
if (p==x) p--;
if (b[i]+a[p].F<=b[1]+a[x].F) return 0;
p--;
}
return 1;
}
bool check2(int x,int y){
int p=1;
for (int i=y;i>=1;i--){
if (p==x) p++;
if (b[i]+a[p].F>b[n]+a[x].F) return 0;
p++;
}
return 1;
}
int main()
{
int _; cin >> _;
while (_--){
cin >> n;
for (int i=1;i<=n;i++){
cin >> a[i].F;
a[i].S=i;
}
for (int i=1;i<=n;i++) cin >> b[i];
sort(a+1,a+n+1); reverse(b+1,b+n+1);
p=n-1;
for (int i=1;i<=n;i++){
while (p>=0&&!check1(i,p)) p--;
ans_worst[a[i].S]=p+1;
}
p=n-1;
for (int i=n;i>=1;i--){
while (p>=0&&!check2(i,p)) p--;
ans_best[a[i].S]=n-p;
}
for (int i=1;i<=n;i++) cout << ans_best[i] << ' ' << ans_worst[i] << endl;
}
return 0;
}
- 思路
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10,mod=1e9+7;
template<typename T>
void Debug(T x,string s){
cout<<s<<": "<<x<<endl;
}
#define PII pair<int,int>
// #define x first
// #define y second
#define PB push_back
void solve()
{
int n,m;
int ans=0;
ll k;
int a1,x;
cin>>n>>m>>k;
vector<int> vec(m+1);
if (k == 1){
for (int i=1; i <= m; ++i) {
cin>>x;
ans=max(x,ans);
}
for (int i=2; i <= n; ++i) {
for(int j=1; j <= m; ++j) cin>>x;
}
}
else if (k%2 == 0) {
for (int i=1; i <= n; ++i) {
for(int j=1; j <= m; ++j) {
cin>>x;
if(i == 1 && j == 1) a1=x;
if (vec[j] == 0 || vec[j] > x) vec[j]=x;
}
}
for (int i=1; i <= m; ++i) ans=max(ans,vec[i]);
ans=max(a1,ans);
}
else if (k%2) {
for (int i=1; i <= n; ++i) {
int _max=0;
for(int j=1; j <= m; ++j) {
cin>>x;
if(i == 1 && j == 1) a1=x;
_max=max(_max,x);
}
if (ans == 0 || ans > _max) ans=_max;
}
ans=max(a1,ans);
}
cout<<ans<<endl;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.txt", "r", stdin);
freopen("aout.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t--)
solve();
}
1007
- 思路
所有操作都可以 O ( 1 ) O(1) O(1) 转移;数组模拟双向链表
- 代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=10000015,mod=1e9+7;
template<typename T>
void Debug(T x,string s){
cout<<s<<": "<<x<<endl;
}
struct node
{
int val,p_cnt;
int next,last;
}a[N];
#define PII pair<int,int>
// #define x first
// #define y second
#define PB push_back
int vis[N],vis_p[N];//value值在链表中的位置,value值对应的数组下标
struct linklist
{
int head=1,tail=1,sz=0,mid=tail;
void insertl(int tot){
if(sz==0){
head=tail=tot;vis_p[tot]=1;
a[tot].last=-1;a[tot].next=-1;
mid=tail;
}
else{
a[tot].next=head;
a[tot].last=-1;
a[head].last=tot;
vis_p[tot]=vis_p[head]-1;
head=tot;
if(sz%2==0){
movel();
}
else{
mid=mid;
}
}
sz++;
}
void insertr(int tot){
if(sz==0){
head=tail=tot;vis_p[tot]=1;
a[tot].last=-1;a[tot].next=-1;
mid=tot;
}
else{
a[tot].last=tail;
a[tot].next=-1;
a[tail].next=tot;
vis_p[tot]=vis_p[tail]+1;
tail=tot;
if(sz%2==1){
mover();
}
}
sz++;
}
void del(int tot){
int tl=a[tot].last,tr=a[tot].next;
// if(tr!=-1)
a[tl].next=tr;
// if(tl!=-1)
a[tr].last=tl;
if(tot==head){
head=a[head].next;
}
if(tot==tail){
tail=a[tail].last;
}
if(mid==tot){
if(sz%2==0) movel();
else mover();
}
else{
if((sz%2==1)&&vis_p[mid]>vis_p[tot]){
mover();
}
if((sz%2==0)&&vis_p[mid]<vis_p[tot])
movel();
}
sz--;
a[tot].last=a[tot].next=-1;
}
void movel(){
mid=a[mid].last;
}
void mover(){
mid=a[mid].next;
}
}List;
int tot=0;
void solve()
{
int posl=0,posr=0;a[0].last=a[0].next=-1;
int q;scanf("%d ",&q);char c;
for(int i=1;i<=q;i++){
scanf("%c ",&c);
if(c=='L'){
List.insertl(++tot);
}
else if(c=='R'){
List.insertr(++tot);
}
else if(c=='G'){
int x;scanf("%d ",&x);
List.del(x);
}
else{
printf("%d\n",List.mid);
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("b.txt", "r", stdin);
freopen("bout.txt", "w", stdout);
#endif
// #ifndef ONLINE_JUDGE
// freopen("a.txt", "r", stdin);
// freopen("aout.txt", "w", stdout);
// #endif
int t;
t=1;
while (t--)
solve();
}
1010
- 思路
- 代码
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 100000 + 10;
const long long inf = 0x7f7f7f7f7f7f7f7fLL;
int A[maxn], B[maxn]; /// 记录评委的评分
int main() {
int T; scanf("%d", &T);
while(T --) {
int n, s, t, h; scanf("%d%d%d%d", &n, &s, &t, &h);
for(int i = 1; i <= n-1; i ++) scanf("%d", &A[i]);
for(int i = 1; i <= n-1; i ++) scanf("%d", &B[i]);
A[n] = 1; A[n+1] = h;
B[n] = 1; B[n+1] = h;
n ++; s ++; t ++; /// n 表示序列中的总元素数
sort(A + 1, A + n + 1);
sort(B + 1, B + n + 1);
long long SumA = 0, SumB = 0; /// 记录一定会被统计到答案中的部分
for(int i = t + 1; i <= n - s; i ++) {
SumA += A[i];
SumB += B[i];
}
long long ans = inf;
/// 第一种情况 A_{n+1} = {1}, B_{n+1} in [B_t, B_{n-s+1}]
long long Btmp = A[t] + SumA - SumB - 1; /// 此时有 B_{n+1} <= Btmp
//printf("SumA = %lld, SumB = %lld, A:(%d, %d), B:(%d, %d)\n", SumA, SumB, A[t], A[n-s+1], B[t], B[n-s+1]);
if(Btmp >= B[t]) {
long long Bt = min(Btmp, (long long)B[n-s+1]);
ans = min(ans, 1 - Bt);
}
/// 第二种情况 A_{n+1} in [A_t, A_{n-s+1}], B_{n+1} = h
long long Atmp = B[n-s+1] + SumB - SumA + 1; /// 此时有 A_{n+1} >= Atmp
if(Atmp <= A[n-s+1]) {
long long At = max((long long)A[t], Atmp);
ans = min(ans, At - h);
}
/// 第三种情况 A_{n+1} = 1, B_{n+1} = h
if(A[t] - B[n-s+1] >= SumB - SumA + 1) {
ans = min(ans, 1ll - h);
}
/// 第四种情况 A_{n+1} in [A_t, A_{n-s+1}], B_{n+1} in [B_t, B_{n-s+1}]
if(A[n-s+1] - B[t] >= SumB - SumA + 1) {
ans = min(ans, max(SumB - SumA + 1, (long long)A[t] - B[n-s+1]));
}
ans == inf ? puts("IMPOSSIBLE") : printf("%lld\n", ans);
}
return 0;
}