版权声明:转载之前请说你是博主的粉丝哦。 https://blog.csdn.net/qq_34921856/article/details/81916054
D Rikka with Prefix Sum
当时一直想着怎么维护,并没有想到每个值对询问的贡献。。
真的是太菜了。
题解说的比较详细了,你只需要推出那个式子就行了。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int mod=998244353;
struct Query
{
int type;
int L,R;
int w;
}q[maxn];
int sum[maxn];
//返回d=gcd(a,b);和对应于等式ax+by=d中的x,y
long long extgcd(long long a,long long b,long long &x,long long &y)
{
if(a==0&&b==0)return -1;//无最大公约数
if(b==0){x=1;y=0;return a;}
long long d=extgcd(b,a%b,y,x);
y-=a/b*x;
return d;//返回gcd(a,b)
}
//****************求逆元******************************
//ax=1(mod n)
long long mod_reverse(long long a,long long n)
{
long long x,y;
long long d=extgcd(a,n,x,y);
if(d==1)return (x%n+n)%n;
return -1;
}
long long tab1[maxn*2],tab2[maxn*2];
void init()
{
tab1[0]=1;
for(int i=1;i<maxn*2;i++)
tab1[i]=tab1[i-1]*i%mod;
tab2[2*maxn-1]=mod_reverse(tab1[2*maxn-1],mod);
for(int i=2*maxn-2;i>=0;i--)
tab2[i]=tab2[i+1]*(i+1)%mod;
}
long long C(int a,int b)
{
if(a<b)return 0;
return tab1[a]*tab2[b]%mod*tab2[a-b]%mod;
}
int main()
{
init();
int T;
scanf("%d",&T);
while(T--)
{
memset(sum,0,sizeof(sum));
int n,m;
scanf("%d %d",&n,&m);
int type,L,R,w;
for(int i=1;i<=m;i++)
{
scanf("%d",&type);
if(type==1)
{
scanf("%d %d %d",&L,&R,&w);
q[i]=(Query){type,L,R,w};
}
else if(type==2)
{
q[i].type=2;
sum[i]++;
}
else
{
scanf("%d %d",&L,&R);
q[i].type=3;
q[i].L=L;
q[i].R=R;
}
sum[i]+=sum[i-1];
}
for(int i=1;i<=m;i++)if(q[i].type==3)
{
long long ans=0;
for(int j=1;j<i;j++)if(q[j].type==1)
{
long long k=sum[i]-sum[j]+1;
int L1=q[j].L,R1=q[j].R;
int L2=q[i].L,R2=q[i].R;
int w=q[j].w;
long long tmp=((C(k+R2-L1,k)-C(k+R2-R1-1,k))%mod+mod)%mod*w%mod;
long long tmp2=((C(k+L2-1-L1,k)-C(k+L2-1-R1-1,k))%mod+mod)%mod*w%mod;
(ans+=((tmp-tmp2)%mod+mod)%mod)%=mod;
}
printf("%lld\n",ans);
}
}
return 0;
}
E Rikka with Equation
这题一点思路都没有。。
首先你要推出每个f的值,也就是
的方案数。
如果
,那么不管前面n-1个x怎么选,最后一个都有值可以使等式成立,所以方案数为
,推广到一般情况,如果gcd值不为1,那么前面的n-1个x随便选,最后一个有gcd种取法。(博主也不知道怎么证。。)
有n个数,
个非空子集,假设它们的gcd都为1,那么答案就为
所以你只需要枚举m,然后算出每个m的因子的ans,再容斥一下就行了。至于为什么要容斥,因为假如一个数的因子有4,那么肯定也会有2,你对因子2进行计算的值会包括4的,所以你得减掉,使得每个数内的值都只是自己的。同时容斥的方向需要注意。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int mod=998244353;
long long inv_m;
int p[maxn];
void push(int x)
{
for(int i=1;i*i<=x;i++)if(x%i==0)
{
if(i*i==x)
p[i]++;
else
{
p[i]++;
p[x/i]++;
}
}
}
long long quick_mul(long long a,long long b)
{
long long res=1;
while(b)
{
if(b%2)res=res*a%mod;
b/=2;
a=a*a%mod;
}
return res;
}
long long inv(long long a,long long m)
{
if(a==1)return 1;
return inv(m%a,m)*(m-m/a)%m;
}
long long F(int m,int n)
{
return ((quick_mul(m+1,n)-1)%mod+mod)%mod*inv_m%mod;
}
long long ct[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(p,0,sizeof(p));
int n,M;
scanf("%d %d",&n,&M);
int b;
for(int i=1;i<=n;i++)
{
scanf("%d",&b);
push(b);
}
long long ans=((quick_mul(2,n)-1)%mod+mod)%mod;
for(int i=2;i<=M;i++)
{
inv_m=inv(i,mod);
vector<int>V;
for(int j=1;j*j<=i;j++)if(i%j==0)
{
if(j*j==i)
V.push_back(j);
else
{
V.push_back(j);
V.push_back(i/j);
}
}
sort(V.begin(),V.end());
for(int j=0;j<V.size();j++)
ct[j]=F(i,p[V[j]]);
for(int j=V.size()-1;j>=0;j--)
{
for(int k=j+1;k<V.size();k++)
if(V[k]%V[j]==0)
{
ct[j]-=ct[k];
ct[j]=(ct[j]%mod+mod)%mod;
}
}
long long res=0;
for(int j=0;j<V.size();j++)
res=(res+1LL*V[j]*ct[j]%mod)%mod;
ans^=res;
}
printf("%lld\n",ans);
}
return 0;
}
F Rikka with Line Graph
式子博主在下面也推出来了,然而并不知道怎么往下做下去。。
看了题解才知道。。
唉。
没啥好说的。
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=505;
const int mod=998244353;
int mp[maxn][maxn];
int d[maxn][maxn];
int n;
void floyd()
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&mp[i][j]),d[i][j]=mp[i][j];
floyd();
long long ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<i;j++)
{
vector<int>V(n);
for(int k=1;k<=n;k++)
V[k-1]=min(d[i][k],d[j][k]);
sort(V.begin(),V.end());
for(int k=0;k<V.size();k++)
{
(ans+=1LL*(n-k-1)*V[k]%mod)%=mod;
}
}
}
long long factor=n*(n-1)/2-1;
for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
ans=(ans+factor*mp[i][j]%mod)%mod;
printf("%lld\n",ans);
}
return 0;
}
H Rikka with Ants
这个题其实式子比较好推,但后面的类欧几里得博主没见过。。
最后的上限的计算也没见过,这里mark一下。
形如
这样的不等式,它的值其实和普通的式子一样算。
所以你求出上限后,套用类欧就行了。
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
typedef long long ll;
long long a,b,c,d;
bool check(long long x)
{
return c*(x+1)/d-a*x/b+1>0;
}
ll solve(ll a, ll b, ll c, ll n) {
if (a == 0) return (((b / c) % mod) * ((n + 1) % mod)) % mod;
if (a >= c || b >= c) {
ll tmp;
if (n & 1) tmp = (n % mod) * ((n + 1) / 2 % mod) % mod;
else tmp = (n / 2 % mod) * ((n + 1) % mod) % mod;
return (solve(a % c, b % c, c, n) + (a / c) * tmp % mod + ((b / c) % mod) * ((n + 1) % mod)) % mod;
}
//ll m = (a * n + b) / c;
ll m;
{
ll d1 = n / c, m1 = n % c;
m = a * d1 + (a * m1 + b) / c;
}
ll v = solve(c, c - b - 1, a, m - 1);
return ((n % mod) * (m % mod) - v) % mod;
}
long long fd(long long a,long long b,long long c,long long n)
{
return solve(a,b,c,n);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
//LL t;
scanf("%lld %lld %lld %lld",&a,&b,&c,&d);
if(a*d==b*c)
{
puts("-1");
continue;
}
if(a*d<b*c)
{
swap(a,c);swap(b,d);
}
long long ans;
ans=(c+d)*b/(d*a-c*b);
//cout<<ans<<endl;
long long res=(((fd(c,c,d,ans)-fd(a,0,b,ans))%mod+mod)%mod+ans+1)%mod;
printf("%lld\n",res);
}
return 0;
}