AGC这么hard的嘛,从A就开始卡题,然后只会AB。。
我可能没有语言表达能力,所以说不太清楚QAQ
A − T r i a n g l e \bf A - Triangle A−Triangle
D e s c r i p t i o n \bf Description Description:在坐标系中找三个整点,使其构成三角形面积为 S / 2 S/2 S/2 , 1 ≤ S ≤ 1 0 18 1 ≤ S ≤ 10^{18} 1≤S≤1018 , 0 ≤ X , Y ≤ 1 0 9 0 \leq X,Y \leq 10^9 0≤X,Y≤109
S o l u t i o n \bf Solution Solution:我也不知道怎么说??设三个点分别在 ( a , 0 ) , ( 0 , b ) , ( x , y ) (a,0) , (0,b) , (x,y) (a,0),(0,b),(x,y),且不妨设 a ≤ x , b ≤ y a \leq x,b\leq y a≤x,b≤y,那么可得 S = 2 x y − a b − ( x − a ) y − x ( y − b ) S=2xy-ab-(x-a)y-x(y-b) S=2xy−ab−(x−a)y−x(y−b) ,整理可得 x y − S = ( x − a ) ( y − b ) xy-S=(x-a)(y-b) xy−S=(x−a)(y−b) 。
为了让 x , y , a , b ≤ 1 0 9 x,y,a,b \leq 10^9 x,y,a,b≤109 ,我们可以这么搞,找一对 x , y x,y x,y 使左边 ≤ 1 0 9 \leq 10^9 ≤109,右边的话,直接 x − a = 1 x-a=1 x−a=1, y − b = x y − S y-b=xy-S y−b=xy−S,然后 x , y x,y x,y 找两个接近 S \sqrt S S 的整数就过了。。
(其实可能还要证一下这样构造会满足 y ≤ x y − S y \leq xy-S y≤xy−S ,但是因为太懒就省略了。。)
好像和官方题解不太一样,好像官方题解会真一点。。
#include<bits/stdc++.h>
#define LL long long
#define fr(i,x,y) for(int i=(x);i<=(y);i++)
#define rf(i,x,y) for(int i=(x);i>=(y);i--)
#define frl(i,x,y) for(int i=(x);i<(y);i++)
using namespace std;
const int N=1002;
LL S;
void read(LL &x){ scanf("%lld",&x); }
int main(){
read(S);
LL x=sqrt(S)+0.0001,y=S/x;
if (x*y<S) x++;
LL v=x*y-S;
LL a=x-1,b=y-v;
printf("%lld %lld %lld %lld %lld %lld\n",a,0,0,b,x,y);
return 0;
}
B − D o N o t D u p l i c a t e \bf B - Do\ Not\ Duplicate B−Do Not Duplicate
D e s c r i p t i o n \bf Description Description:给一个长度为 N N N 的数列 A A A ,将 A A A 重复 K K K 次得到数列 X X X ,将 X X X 中的数依次加入 s s s 中,规则是这样的:
- 如果 s s s 中没有 X i X_i Xi 这个数,将 X i X_i Xi 加到末尾
- 如果有,从末尾一直删除,直到数列中没有 X i X_i Xi (不再加入)
求数列 s s s 。
S o l u t i o n \bf Solution Solution:为什么感觉AGC的题解好难写,一种说不清的感觉。。这题的话,我们关心一下每次数列被清空是啥时候,如果这次在加入 A i A_i Ai 的时候是空的,那么 s s s 第一个数就变成了 A i A_{i} Ai ,那下次清空就是再次出现 A i A_i Ai 的时候,设为 A j A_j Aj ,那么接下去 s 的第一个数就变成了 A j + 1 A_{j+1} Aj+1 。于是,我们从 i i i 向 j + 1 j+1 j+1 连一条边。沿着边走就会出现环,相当于有循环节,把循环节从 N × K N \times K N×K 里去掉,剩下的暴力就行。
具体可能还是要看代码实现,但是我代码很丑呢。。
#include<bits/stdc++.h>
#define LL long long
#define fr(i,x,y) for(int i=(x);i<=(y);i++)
#define rf(i,x,y) for(int i=(x);i>=(y);i--)
#define frl(i,x,y) for(int i=(x);i<(y);i++)
using namespace std;
const int N=200002;
int n,a[N];
int b[N];
int h[N],w;
int to[N];
LL K;
void read(int &x){ scanf("%d",&x); }
void read(LL &x){ scanf("%lld",&x); }
void gooo(int p,int s){ //暴力按题意加入数字
memset(b,0,sizeof b);
fr(i,1,s){
if (!b[a[p]]) h[++w]=a[p],b[a[p]]=1;
else{
while(h[w]!=a[p]) b[h[w]]=0,w--;
b[h[w]]=0;w--;
}
p=p%n+1;
}
fr(i,1,w) printf("%d ",h[i]);
}
void goo(int p,LL s){ //暴力跳到最后一次清空
while(to[p]-p+1<=s){
s-=to[p]-p+1;
p=to[p]%n+1;
}
gooo(p,s);
}
int main(){
read(n);read(K);
fr(i,1,n) read(a[i]);
rf(i,n,1) b[a[i]]=i+n;
rf(i,n,1) to[i]=b[a[i]],b[a[i]]=i;
memset(b,0,sizeof b);
int p=1;LL s=0,sc=0; //s表示从1走完循环节的总次数,sc表示循环节上的总次数
while(!b[p]){
b[p]=1;
s+=to[p]-p+1;
p=to[p]%n+1;
}
int q=p;
while(1){
sc+=to[q]-q+1;
q=to[q]%n+1;
if (q==p) break;
}
if (n*K<=s) goo(1,n*K);
else goo(p,(n*K-s)%sc);
return 0;
}
C − G P 2 \bf C - GP 2 C−GP2
D e s c r i p t i o n \bf Description Description:一个长度为 n n n 的数列初始都为 0 0 0 。一次操作可以选择两个不同的位置,一个 + 1 +1 +1 ,一个 + 2 +2 +2 ,问 M M M 次操作后形成的数列有多少种可能,模 998244353 998244353 998244353 。
S o l u t i o n \bf Solution Solution:可以发现最后形成数列是合法的充要条件如下
- ∑ i = 1 n x i = 3 M \sum_{i=1}^n x_i=3M ∑i=1nxi=3M
- m a x { x 1 , x 2 , ⋯   , x n } ≤ 2 M max\{x_1,x_2,\cdots,x_n\} \leq 2M max{x1,x2,⋯,xn}≤2M
- ∑ i = 1 n [ x i m o d 2 = 1 ] ≤ M \sum_{i=1}^n [x_i \ mod \ 2=1] \leq M ∑i=1n[xi mod 2=1]≤M
不证了,感性理解下= =这个结论我倒是发现了,但是不知道是不是因为太久没做TC,数数水平下降到哪里去都不知道了QAQ。
先不考虑第二个条件emmm。。然后我们可以枚举有几个奇数,总数就是 ∑ i = 1 M ( n i ) ⋅ ( ( 3 M − i ) / 2 + n − 1 n − 1 ) \sum_{i=1}^M {n \choose i} \cdot {(3M-i)/2+n-1 \choose n-1} i=1∑M(in)⋅(n−1(3M−i)/2+n−1)
考虑把不满足第二的条件的答案踢出去。注意到大于 2 M 2M 2M 的数最多只有一个,把它减去 2 M 2M 2M 后,问题就转化为求下面这个数列的数量(不妨设这个大于 2 M 2M 2M 的数为 x 1 x_1 x1 ,最后要乘 n n n)
- ∑ i = 1 n x i = M \sum_{i=1}^n x_i=M ∑i=1nxi=M
- ∑ i = 1 n [ x i m o d 2 = 1 ] ≤ M \sum_{i=1}^n [x_i \ mod \ 2=1] \leq M ∑i=1n[xi mod 2=1]≤M
- x 1 > 0 x_1>0 x1>0
如果无视第三个条件的话,好像和上面求法差不多呢0_0
然后考虑怎么把不符合第三个条件的踢出去。那样的话 x 1 = 0 x_1=0 x1=0,问题又转化了:
- ∑ i = 2 n x i = M \sum_{i=2}^n x_i=M ∑i=2nxi=M
- ∑ i = 2 n [ x i m o d 2 = 1 ] ≤ M \sum_{i=2}^n [x_i \ mod \ 2=1] \leq M ∑i=2n[xi mod 2=1]≤M
还是一样的求法呢。。
贴代码
#include<bits/stdc++.h>
#define LL long long
#define fr(i,x,y) for(int i=(x);i<=(y);i++)
#define rf(i,x,y) for(int i=(x);i>=(y);i--)
#define frl(i,x,y) for(int i=(x);i<(y);i++)
using namespace std;
const int N=3000002;
const int p=998244353;
int n,m;
LL mul[N],inv[N];
LL ans;
void read(int &x){ scanf("%d",&x); }
void read(LL &x){ scanf("%lld",&x); }
LL qpow(LL a,int n){
LL ans=1;
for(LL sum=a;n;n>>=1,sum=sum*sum%p) if (n&1) ans=ans*sum%p;
return ans;
}
void init(){
mul[0]=1;
frl(i,1,N) mul[i]=mul[i-1]*i%p;
inv[N-1]=qpow(mul[N-1],p-2);
rf(i,N-2,0) inv[i]=inv[i+1]*(i+1)%p;
}
LL C(int n,int m){
if (n<0||m<0||n-m<0) return 0;
return mul[n]*inv[m]%p*inv[n-m]%p;
}
void Add(LL &x,LL y){
x+=y;
while(x<0) x+=p;
while(x>=p) x-=p;
}
int main(){
read(n);read(m);
init();
fr(i,0,m)
if ((3*m-i)%2==0) Add(ans,C(n,i)*C((3*m-i)/2+n-1,n-1)%p);
fr(i,0,m)
if ((m-i)%2==0) Add(ans,-C(n,i)*C((m-i)/2+n-1,n-1)%p*n%p);
fr(i,0,m)
if ((m-i)%2==0) Add(ans,C(n-1,i)*C((m-i)/2+n-2,n-2)%p*n%p);
cout<<ans<<endl;
return 0;
}
D − N e g a t i v e C y c l e \bf D - Negative \ Cycle D−Negative Cycle
后面的,可能也不太懂,先咕咕咕。。