• 10.22 模拟赛


    10.22 模拟赛

    T1 染色

    考虑每个连通块删成一棵树就好了。

    mmp场上就我路径压缩写炸。。。。

    f[1<<21],n,m,t;F(x){t=f[x];return x^t?f[x]=!t?x:F(t):x;}main(s){for(scanf("%*d%d",&s);~scanf("%d%d",&n,&m);f[F(m)]=F(n))s-=F(n)!=F(m);exit(!printf("%d",s));}
    

    T2 乘方

    首先,二分答案,变成一个判定问题。

    如果只有一个集合,比一个数字小的数字个数就是 $ sqrt[n]{m} $

    然后如果是一些集合交,可以直接把这些集合取 $ lcm $ ,可以证明是对的。

    然后可以 $ 2^k $ 枚举子集容斥

    当然,这个容斥看起来就可以dp

    然后dp就对了,设 $ dp[i][j] $ 表示前 i 个数,LCM为一个 j 的子集的容斥系数

    记得开根号二分。。不然T惨

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define int long long
    #define MAXN 62
    typedef long long ll;
    int fuck[MAXN][MAXN];
    inline int gcd( int a , int b ) { return b ? gcd( b , a % b ) : a; }
    inline int lcm( int x , int y ) { 
    if (fuck[x][y]) return fuck[x][y];
    return fuck[x][y] = fuck[y][x] = x * y / gcd( x , y ); 
    }
    int m , k;
    int A[MAXN];
    int dp[MAXN][MAXN];
    
    inline ll calc(ll n, int k)
    {
    	ll val = 1;
    	for (int i = 0; i < k; i++)
    	{
    		if ((double)val * n >= 100000000000000000LL)
    			return 100000000000000000LL;
    		val *= n;
    	}
    	return val;
    }
    inline ll sqrt(ll n, int k)
    {
    	ll res = std::pow(n, 1.0 / k);
    	while (calc(res, k) < n)
    		res++;
    	while (calc(res, k) > n)
    		res--;
    	return res - 1;
    }
    int qpow(int x,int y)
    {
    	int res=1;
    	while(y)
    	{
    		if(y&1)
    		{
    			if(res*x<=0||res*x>1e17)return -1;
    			res*=x;
    		}
    		y>>=1;
    		if(!y)break;
    		if(x*x<=0||x*x>1e17)return -1;
    		x*=x;
    	}
    	return res;
    }
    int lim[MAXN];
    int get(int x,int v)
    {
    	int l=1,r=lim[x],res=1;
    	if(x>60)return 1;
    	while(l<=r)
    	{
    		int mid=(l+r)>>1;
    		int re=qpow(mid,x);
    		if(re<=v&&(re!=-1))res=mid,l=mid+1;
    		else r=mid-1;
    	}
    	return res;
    }
    inline bool chk( int x ) {
    	long long res = 0;
    	for( int n = 1 ; n < MAXN ; ++ n )
    		res += dp[k][n] * get( n , x ) - dp[k][n];
    //	cout << res << endl;
    	return res >= m;
    }
    signed main() {
    	lim[2]=1e9;lim[3]=1e6;lim[4]=sqrt(lim[2])+15;lim[5]=4500;lim[6]=2000;
    	for(int i=7;i<=60;++i)
    	{
    		for(int j=1;;++j)
    		{
    			int now=qpow(j,i);
    			if(now==-1)break;
    			lim[i]=j;
    		}
    	}
    	int t; cin >> t;
    	while( t-- ) {
    		scanf("%lld%lld",&m,&k), m--;
    		int flag = 0;
    		for( int i = 1 ; i <= k ; ++ i ) { scanf("%lld",&A[i]); if( A[i] == 1 ) flag = 1; }
    		if( flag ) { cout << m + 1 << endl; continue; }
    		memset( dp , 0 , sizeof dp );
    		dp[1][A[1]] = 1;
    		for( int i = 1 ; i < k ; ++ i ) {
    			dp[i + 1][A[i + 1]] = 1;
    			for( int n = 1 ; n < MAXN ; ++ n ) if (dp[i][n]) {
    				dp[i + 1][n] += dp[i][n];
    				if( lcm(n, A[i + 1]) < MAXN )
    					dp[i + 1][lcm(n, A[i + 1])] -= dp[i][n];
    			}
    		}
    //		for (int i = 2; i <= 50; i++)
    //			cout << dp[k][i][0] - dp[k][i][1] << ' ';
    //		cout << endl;
    //		chk(64);
    		ll l = 1 , r = 100000000000000006LL, ans = -1;
    		while( l <= r ) {
    			int mid = l + r >> 1;
    			if( chk( mid ) ) ans = mid, r = mid - 1;
    			else l = mid + 1;
    		}
    		cout << ans << endl;
    	}
    }
    

    T3 位运算

    and 可以用 这里 的 F 的做法来做,复杂度 $ O(n + v) $ 当然也可以贪心 $ O(nlogv) $

    xor 可以用trie直接做

    or 不会。貌似只能FWT

    所以就粘板子 FWT 跑就行了,直接求位运算卷积就做完了。

    当 FWT 板子放在这里把

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<bitset>
    #include<set>
    using namespace std;
    //#define int long long
    typedef long long ll;
    #define MAXN 8388610 
    #define MAXV 8388610
    #define pb push_back
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define mp make_pair
    #define inf 0x3f3f3f3f
    #define cmx( a , b ) a = max( a , b )
    #define cmn( a , b ) a = min( a , b )
    #define upd( a , b ) ( a = ( a + b ) % P )
    #define swap( a , b ) a = a ^ b , b = a ^ b , a = a ^ b
    #define P 1000000007
    int n , q;
    int A[MAXN];
    
    namespace fwt {
    	
    	inline void FWT1(ll a[], int len) {
    		for (int mid = 2; mid <= len; mid <<= 1) 
    			for (int i = 0; i < len; i += mid)
    				for (int j = i; j < i + (mid >> 1); j++) 
    					a[j + (mid >> 1)] += a[j];
    	}
    	
    	inline void IFWT1(ll a[], int len) {
    		for (int mid = 2; mid <= len; mid <<= 1) 
    			for (int i = 0; i < len; i += mid)
    				for (int j = i; j < i + (mid >> 1); j++) 
    					a[j + (mid >> 1)] -= a[j];
    	}
    	
    	inline void FWT2(ll a[], int len) {
    		for (int mid = 2; mid <= len; mid <<= 1) 
    			for (int i = 0; i < len; i += mid)
    				for (int j = i; j < i + (mid >> 1); j++) 
    					a[j] += a[j + (mid >> 1)];
    	}
    	
    	inline void IFWT2(ll a[], int len) {
    		for (int mid = 2; mid <= len; mid <<= 1) 
    			for (int i = 0; i < len; i += mid)
    				for (int j = i; j < i + (mid >> 1); j++) 
    					a[j] -= a[j + (mid >> 1)];
    	}
    	
    	inline void FWT3(ll a[], int len) {
    		for (int mid = 2; mid <= len; mid <<= 1) 
    			for (int i = 0; i < len; i += mid)
    				for (int j = i; j < i + (mid >> 1); j++) {
    					ll x = a[j], y = a[j + (mid >> 1)];
    					a[j] = x + y, a[j + (mid >> 1)] = x - y;
    				}
    	}
    	
    	inline void IFWT3(ll a[], int len) {
    		for (int mid = 2; mid <= len; mid <<= 1) 
    			for (int i = 0; i < len; i += mid)
    				for (int j = i; j < i + (mid >> 1); j++) {
    					ll x = a[j], y = a[j + (mid >> 1)];
    					a[j] = (x + y) >> 1, a[j + (mid >> 1)] = (x - y) >> 1;
    				}
    	}
    	
    	ll a[MAXN], b[MAXN]; int input[400010];
    	
    	int main() {
    		int mx = 0, len = 1; 
    		for (int i = 1, x; i <= n; i++) 
    			a[A[i]]++, b[A[i]]++, mx = max(mx, A[i]), input[i] = A[i];
    		while (len <= mx) len <<= 1;
    		if (q == 1) {
    			FWT2(a, len);
    			for (int i = 0; i < len; i++) a[i] = a[i] * a[i];
    			IFWT2(a, len);
    			for (int i = len - 1; i >= 0; i--) if (a[i]) {
    				ll res = (a[i] - b[i]) >> 1;
    				if (res) return printf("%d %lld", i, res), 0;
    			}
    		} else if (q == 2) {
    			bool flag = true;
    			for (int i = 2; i <= n; i++) 
    				if (input[i] != input[1]) {
    					flag = false; break;
    				}
    			if (flag) return printf("0 %lld", (ll)n * (n + 1) / 2), 0;
    			FWT3(a, len);
    			for (int i = 0; i < len; i++) a[i] = a[i] * a[i];
    			IFWT3(a, len);
    			for (int i = len - 1; i >= 0; i--) if (a[i]) 
    				return printf("%d %lld", i, a[i] >> 1), 0;
    		} else {
    			FWT1(a, len);
    			for (int i = 0; i < len; i++) a[i] = a[i] * a[i];
    			IFWT1(a, len);
    			for (int i = len - 1; i >= 0; i--) if (a[i]) {
    				ll res = (a[i] - b[i]) >> 1;
    				if (res) return printf("%d %lld", i, res), 0;
    			}
    		}
    	}
    
    }
    
    
    int main() {
        cin >> n >> q;
        int mx = 0;
        for( int i = 1 ; i <= n ; ++ i ) scanf("%d",&A[i]) , mx = max(A[i] , mx);
    	fwt::main();
    	
    }
    
  • 相关阅读:
    jQuery基础教程-第8章-002Adding jQuery object methods
    jQuery基础教程-第8章-001Adding new global functions
    福利彩票-001什么是福利彩票
    Java生产者消费者问题
    Java集合
    Java线程
    JavaPersistenceWithMyBatis3笔记-第5章Configuring MyBatis in a Spring applications-001
    CentOS安装和配置Apache(httpd)
    CentOS安装和配置FTP
    PHP 常用获取路径代码
  • 原文地址:https://www.cnblogs.com/yijan/p/1022comp.html
Copyright © 2020-2023  润新知