又是一天的考试,又是一天的爆0。
Day 2
T1 Calc
一道数学竞赛题,非常的神奇。主要是要把题目所求转化为组合计数。
原题的公式是
∑nk1=0∑nk2=0⋅⋅⋅⋅⋅∑nkm=0∏m−1j=1(kj+1kj)
可以得到公式
ANS=∑nk=0mk=mn+1−1m−1
最后用费马小定理与逆元完成计算。
#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
long long sum=1;
void ksm(long long a,long long b)
{
if(b==1)
{
sum=(sum*a)%mod;
return;
}
if(b%2==1)
sum=(sum*a)%mod;
a=(a*a)%mod;
b=b/2;
ksm(a,b);
}
int main()
{
int n,m;
cin>>n>>m;
ksm(m,n+1);
long long sum1=sum-1;
sum=1;
ksm(m-1,mod-2);
cout<<(long long)((sum1)*(sum))%mod;
}
T2 Chess
是全卷最难的一道题,因为每一个车会控制一行和一列,所以将列和行分开计算。
使用两个map
进行维护。
时间复杂度
O(n∗logn2)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <cctype>
using namespace std;
int n,k,q;
long long Sol;
map<int,int> RCnt,CCnt;
map<int,int> RXor,CXor;
map<pair<int,int>,int> Rook;
void MoveRook(int r,int c,int Val) {
int Rxor=RXor[r],Cxor=CXor[c];
Sol-=n-RCnt[Cxor];
Sol-=n-CCnt[Rxor];
--RCnt[Rxor];
Rxor=RXor[r]^=Val;
++RCnt[Rxor];
--CCnt[Cxor];
Cxor=CXor[c]^=Val;
++CCnt[Cxor];
Sol+=n-CCnt[Rxor];
Sol+=n-RCnt[Cxor];
Rook[pair<int,int>(r,c)]^=Val;
}
void Init() {
cin>>n>>k>>q;
RCnt[0]=CCnt[0]=n;
for(int i=0;i^k;++i) {
int r,c,Val;
cin>>r>>c>>Val;
--r;
--c;
MoveRook(r,c,Val);
}
}
void Solve() {
while(q--) {
int r1,c1,r2,c2;
cin>>r1>>c1>>r2>>c2;
--r1;
--c1;
--r2;
--c2;
int RookVal=Rook[pair<int,int>(r1,c1)];
MoveRook(r1,c1,RookVal);
MoveRook(r2,c2,RookVal);
cout<<Sol<<endl;
}
}
int main() {
Init();
Solve();
return 0;
}
T3 Function
因为一个数被取模最多 logx2 次,所以关键便是找到下一次被mod的位置即可。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<iostream>
#include<cctype>
using namespace std;
int l,r,now,pl,n,m;
int num[100010];
struct node
{
int min;
}tree[400010];
inline void R(int &v)
{
char c=0;
v=0;
while(!isdigit(c))
c=getchar();
while(isdigit(c))
{
v=(v<<3)+(v<<1)+(c^'0');
c=getchar();
}
}
void updata(int k)
{
tree[k].min=min(tree[k<<1].min,tree[k<<1|1].min);
}
void read()
{
R(n);
for(int i=1;i<=n;++i)
R(num[i]);
}
void build(int k,int s,int t)
{
if(s==t)
{
tree[k].min=num[s];
return ;
}
int mid=(s+t)>>1;
build(k<<1,s,mid);
build(k<<1|1,mid+1,t);
updata(k);
}
void query(int k,int s,int t,int l,int r)
{
if(tree[k].min>now)
return ;
if(pl<=r)
return ;
if(l<=s&&t<=r)
{
if(s==t)
{
pl=s;
return ;
}
int mid=(s+t)>>1;
query(k<<1,s,mid,l,r);
query(k<<1|1,mid+1,t,l,r);
}
int mid=(s+t)>>1;
if(l<=mid)
query(k<<1,s,mid,l,r);
if(r>mid)
query(k<<1|1,mid+1,t,l,r);
}
int main()
{
read();
build(1,1,n);
R(m);
while(m--)
{
R(l);
R(r);
now=num[l];
l++;
while(now&&l<=r)
{
pl=n+1;
query(1,1,n,l,r);
if(pl>r)
break;
now%=num[pl];
l=pl+1;
}
cout<<now<<'\n';
}
return 0;
}