E. Maximum Flow
https://nanti.jisuanke.com/t/17118
从0到n-1,n个点,权值为点标号,每个点都有 向标号大于自己的点有一条有向边,边权为两结点权值异或值
求从0到n-1的最大流量
找到规律是结果为sum(max(i,i^(n-1))(i=1->n-1)
然后就可以根据数位来求这个结果了
#include<bits/stdc++.h>
using namespace std;
const int mo=1e9+7;
long long a[100];
int main()
{
long long n,i,j;
while(~scanf("%lld",&n))
{
n--;
long long ans=n;
long long temp=n;
int i=0;
while(temp)
{
a[i++]=temp&1;
temp>>=1;
}
temp=(1ll<<(i-1))-1;
n-=temp+1;
if(temp&1)
ans=(ans+((temp+1)/2)%mo*(temp%mo)%mo)%mo;
else
ans=(ans+(temp/2)%mo*((temp+1)%mo)%mo)%mo;
i--;
long long now=0;
for(j=i-1;j>=0;j--)
{
long long t1=(1ll<<j)%mo;
long long t2=now*t1%mo;
if(a[j])
{
ans=(ans+(t2+t1)*t1%mo)%mo;
}
else
{
ans=(ans+t2*t1%mo)%mo;
}
now<<=1;
now+=a[j];
}
printf("%lld\n",ans);
}
return 0;
}
F. Trig Function
https://nanti.jisuanke.com/t/17119
题意很简单
做法,套一个倍角公式
sin^2=1-cos^2
带进去,后面一项换为一个二项式:(1-cos^2)^ i 二项式展开,显然我们只需要求的是其中某一项的系数
令k=(m-(n-2*i))/2
我们需要的那个二项式的系数也就是C(i , k) * (-1) ^ k
大组合数,lucas定理求,但复杂度似乎并不够
其实仔细看看公式,组合数可以依次递推出来,当时卡了半天,没脑子。。。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mo=998244353;
const long long N=998244353;
ll qpow(ll a,ll k)
{
ll ans=1;
while(k)
{
if(k&1)
ans=(ans*a)%mo;
a=(a*a)%mo;
k>>=1;
}
return ans;
}
ll C(ll a,ll b)
{
if(a<b)
return 0;
if(b>a-b)
b=a-b;
ll up=1,down=1;
for(ll i=0;i<b;i++)
{
up=up*(a-i)%mo;
down=down*(i+1)%mo;
}
return up*qpow(down,mo-2)%mo;
}
long long inv[6005000],fac[6005000];
void init()
{
inv[0] = fac[0] = inv[1] = fac[1] = 1;
for(int i = 1; i < 6000000+10; i++)
fac[i] = fac[i - 1] * i % N;
for(int i = 2; i < 6000000+10; i++)
inv[i] = (N - (N / i)) * inv[N % i] % N;//lucas?????
for(int i = 1; i < 6000000+10; i++)
inv[i] = inv[i - 1] * inv[i] % N;
}
ll Comb(int n, int m)//???? C n,m
{
return (fac[n] * inv[m] % N) * inv[n - m] %N;
}
ll lucas(ll a,ll b)
{
if(a<b||a<0||b<0)
return 0;
if(b==0)
return 1;
if(a<=6000000)
return Comb(a,b);
return C(a%mo,b%mo)*lucas(a/mo,b/mo)%mo;
}
int main()
{
int n,m,i;
init();
while(~scanf("%d %d",&n,&m))
{
if(((n-m)&1)||n<m)
printf("0\n");
else
{
long long ans=0;
int i=(n-m)/2;
int k=(m-n+2*i)/2;
long long temp2=lucas(n,2*i);
long long temp3=lucas(i,k);
for(;2*i<=n;i++,k++)
{
// cout<<i<<" "<<k<<endl;
ans=(ans+temp2*temp3%mo*((k&1)?-1:1)*((i&1)?-1:1)+mo)%mo;
temp3=(temp3+temp3*(i-k)%mo*qpow(k+1,mo-2))%mo;
temp2=(temp2*(n-2*i)%mo*(n-2*i-1)%mo*qpow(2*i+1,mo-2)%mo*qpow(2*i+2,mo-2))%mo;
}
printf("%lld\n",ans);
}
}
return 0;
}