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; }