zoukankan      html  css  js  c++  java
  • CF #643(div.2)

    A. Sequence with Digits

    time limit per test: 1 second
    memory limit per test: 256 megabytes

    题意: 给定如下递推式

    [a_{n+1}=a_n+minDigit(a_n) cdot maxDigit(a_n). ]

    其中 (minDigit(a_n))(maxDigit(a_n)) 分别代表 (a_n) 十进制表示中 最小 和 最大 的数字,给出 (a_1)(k) ,让你求 (a_k)

    (t~(1 leq t leq 1000)) 组测试数据,每组数据给出 (a_1)(k~(1 leq a_1 leq 10^{18},1 leq k leq 10^{16}))

    分析: 只要第一次 (minDigit(a_i)=0) 出现,那么 (a_i,a_{i+1},...) 的值都不会变,所以按照公式递推直到算出 (a_k) 或者出现 (minDigit(a_i)=0) 终止就好了 (关于 (0) 在有限且不高次内一定会出现就不证明了,也不咋会证)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define ll long long
    
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(nullptr);
    	
    	ll t,n,k;
    	cin>>t;
    	while(t--)
    	{
    		cin>>n>>k;
    		if(k==1){
    			cout<<n<<endl;
    			continue;
    		}
    		k--;
    		while(k--)
    		{
    			ll tmp=n;
    			ll Min=9,Max=0;
    			while(tmp)
    			{
    				ll res=tmp%10;
    				tmp/=10;
    				Min=min(Min,res);
    				Max=max(Max,res);
    			}
    			if(Min==0) break;
    			else n+=Min*Max;
    		}
    		cout<<n<<endl;
    	}
    } 
    

    B. Young Explorers

    time limit per test: 2 seconds
    memory limit per test: 256 megabytes

    题意: (T~(1 leq T leq 2 cdot 10^5)) 组测试数据,每组给出 (N~(1 leq N leq 2 cdot 10^5)) 和大小为 (N) 的数组 (e~(1 leq e_i leq N))

    (sum N leq 3 cdot 10^5)

    对于每组数据,你需要把数组 (e) 分成尽可能多的组(不必所有的元素都必须分配),但是每组内的元素需要满足 组的大小大于等于组内任意一个元素,即对于一个大小为 (m) 的组 (b) ,需要满足 (b_i leq m)

    求最多可以分成多少组?

    分析: 贪心,把数组 (e) 排序 然后从小到大尽量分组划分;

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    const int N = 3E5+10;
    int a[N];
    
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(nullptr);
    	
    	int t,n;
    	cin>>t;
    	while(t--)
    	{
    		cin>>n;
    		rep(i,1,n) cin>>a[i];
    		sort(a+1,a+n+1);
    		int ans=0,xb=1;
    		while(xb<=n&&xb+a[xb]-1<=n){
    			if(a[xb]==a[xb+a[xb]-1]) ans++,xb+=a[xb];
    			else{
    				int num=a[xb];
    				xb+=a[xb]-1;
    				while(xb+1<=n&&num<a[xb]) num++,xb++;
    				if(num==a[xb]) ans++,xb++;
    				else break;
    			}
    		}
    		cout<<ans<<endl;
    	}
    } 
    

    C. Count Triangles

    time limit per test: 1 second
    memory limit per test: 256 megabytes

    题意: 给定 (A,B,C,D~(1 leq A leq B leq C leq D leq 5 cdot 10^5)) ,求有多少组 ((x,y,z)) 满足 (A leq x leq B leq y leq C leq z leq D) 且构成非退化三角形;

    分析: 因为 (x leq y leq z) ,差分一下 (x+y) 的出现次数 然后求一遍前缀和 再枚举 (z)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    const int N = 1E6+10;
    
    int A,B,C,D;
    ll num[N];
    
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(nullptr);
    	
    	cin>>A>>B>>C>>D;
    	rep(i,A,B)
    	{
    		num[i+B]++;
    		num[i+C+1]--;
    	}
    	rep(i,1,N-1) num[i]+=num[i-1];  //第一遍求出num[i]表示x+y==i有几种
    	rep(i,1,N-1) num[i]+=num[i-1];  //第二遍求前缀和
    	ll ans=0;
    	rep(i,C,D) ans+=num[N-1]-num[i];
    	cout<<ans; 
    }
    
    

    D. Game With Array

    time limit per test: 1 second
    memory limit per test: 256 megabytes

    题意: 给定 (N)(S~(1 leq N leq S leq 10^6)) ,现在要你构造出一个大小为 (N) 的数组 (s~(0<s_i leq S)) 然后选择一个数 (K~(0 leq K leq S)),在数组满足 (sum s_i=S) 的情况下,无法在数组中选取若干元素的和 (sum) 使得 (sum=K~~or~~sum=S-K)

    分析: 构造方法不只一种,但是 (S<2*N) 肯定无解,然后考虑 (K=1) 的话,构造出 (2,2...,S-2*(N-1)) 这类形式的序列,就可以满足题意

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(nullptr);
    	
    	int n,s;
    	cin>>n>>s;
    
    	if(2*n>s)
    	{
    		cout<<"NO";
    		return 0;
    	}
    	cout<<"YES
    ";
    	for(int i=1;i<n;i++) cout<<2<<' ';
    	cout<<s-2*(n-1)<<endl;
    	cout<<1; 
    } 
    

    E. Restorer Distance

    time limit per test: 1 second
    memory limit per test: 256 megabytes

    题意: 先给出 (N,A,R,M~(1 leq N leq 10^5,0 leq A,R,M leq 10^4)) ,然后给出大小为 (N) 的数组 (h~(0 leq h_i leq 10^9)) 分别代表 (N) 根砖柱的高度(1单位高度代表一块砖),现在有三种操作

    • 花费代价 A ,在某一根砖柱上加一块砖
    • 花费代价 R ,从某一根砖柱上拿走一块砖
    • 花费代价 M ,从某一根砖柱上拿一块砖放到另一根砖柱上

    现在要求用最小的代价使得所有砖柱高度一致

    分析: 三分

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    const int MAXN = 1E5+10; 
    
    int N,A,R,M; 
    ll a[MAXN],sum[MAXN];
    
    ll cal(ll H)
    {
    	int x=1;
    	while(x<=N&&a[x]<H) x++;
    	ll left=0;
    	if(x<=N) left=sum[N]-sum[x-1]-H*(N-x+1);
    	ll need=0;
    	if(x>1) need=H*(x-1)-sum[x-1];
    
    	ll cost=0;
    	if(A+R>=M){
    	    if(left>=need) cost+=need*M,left-=need,need=0;
    	    else cost+=left*M,need-=left,left=0; 
    	}
    	cost+=left*R;
    	cost+=need*A;
    	return cost;
    }
    
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(nullptr);
    	
    	cin>>N>>A>>R>>M;
    	rep(i,1,N) cin>>a[i];
    	sort(a+1,a+N+1);
    	rep(i,1,N) sum[i]=sum[i-1]+a[i];
    	ll L=0,R=1E9+1;
    	while(L+1<R)
    	{
    		ll m1=(L+R)>>1;
    		ll m2=(m1+R)>>1;
    		if(cal(m1)<cal(m2)) R=m2;
    		else L=m1;
    	} 
    	ll ANS=cal(L);
    	cout<<ANS;
    } 
    

    F. Guess Divisors Count

    time limit per test: 2 seconds
    memory limit per test: 256 megabytes

    题意: 交互题,预先设定一个数 (X~(1 leq X leq 10^9)) ,让你通过交互得出 (X) 有多少个因数,你有至多 22 次询问,每次询问形式 ? Q ((1 leq Q leq 10^{18})) ,然后会反馈 GCD(X,Q) ,即最大公约数;设 (X) 实际有 (d) 个因数,你给出的答案为 (ans) ,那么只要

    1. (|ans-d| leq 7)
    2. (frac{1}{2} leq frac{ans}{d} leq 2)

    至少满足上述两个条件之一,就判正确

    分析: 肯定会先想到素数分解的形式:(X=p_1^{a_1} cdot p_2^{a_2} cdots p_m^{a_m}) ,那么 (d=(a_1+1)*(a_2+1) cdots (a_m+1)) ;然后明确一点,题目给定了误差限制,所以可以推测不可能在 22 次询问里求得准确答案,即不是 X 的每个素因子都能询问到,可以从这一点考虑:

    • 只有 22 次询问机会,((1 leq X leq 10^9))((1 leq Q leq 10^{18})),所以,1 次询问考虑询问多个素数的乘积;
    • 考虑多个素数的乘积 ((1 leq Q leq 10^{18})) ,其中若有较小的素数,那么它的次数肯定不能是 1 ,否则若 (X) 中关于这个素数的次数很高那么这个素数的询问完全是没有用的,所以得提高次数;然后,最小的素数是 2 且 (2^{30}>10^9 geq X) ,所以可以 以 (2^{10}=1024) 为上界,提高乘积内每个素数的次数,这样一个 Q 内大概会有 5,6 个素数,22 次询问从小到大 大概可以询问到 八百多的素数;极端情况下,我们计算的某个素数的次数可能只统计了刚好超过 (frac{1}{3}) ,例如 (X=2^{29});所以得出最后的结果再乘以 2 ,即 ans*2,那么对于已经计算过的素数误差完全是在条件2范围内的,而对于之后的素数出现的情况,分情况考虑:
    • 若之后的素数出现了 3 次,那么前面的素数一个都不会出现,因为 ((1 leq X leq 10^9)),标准因数个数最大为 (d=2 imes 2 imes 2=8),而我们 ans 初始是1,最后乘以2,(|ans-d| leq 7) 成立,满足条件 1;
    • 若之后的素数出现了 2 次,那么前面的素数的所有出现次数完全被计算了(因为 (1 leq X leq 10^9)),除开后面的两个素数之后,X 最多只剩下 1000 左右;此时后面的素数 d 的影响最多是 (2 imes 2=4) 倍级别,所以 ans*2 之后是满足条件 2 的;
    • 若之后的素数出现了 1 次,极端情况下,前面的素数最多被少算了 1 倍 ,例如 (X=2^{20} imes 863),此时 ans*2 之后依旧满足条件 2;

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    #define ll unsigned long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    const int N = 1000;
    vector<ll>pm;  //素数
    vector<ll>pp;  //提高次数的素数
    vector<ll>test; //多个提高次数的素数的乘积
    
    void ready()
    {
    	bool vis[N]={0};
    	rep(i,2,N-1)if(!vis[i]){
    		pm.pb(i);
    		for(int j=i;j<N;j+=i) vis[j]=1;
    	}
    	for(auto v:pm)
    	{
    		ll x=v;
    		while(x*v<=1024)x*=v;
    		pp.pb(x);
    	}
    	ll res=1;
    	int cnt=0;
    	for(auto v:pp)
    	{
    		if(res*v>1e18) test.pb(res),res=v,++cnt;
    		else res*=v;
    		if(cnt==22) {cout<<"---"<<v<<endl;break;} 
    	}
    	if(res>1) test.pb(res);
    	
    }
    
    ll ask(ll m)
    {
    	cout<<"? "<<m<<endl;
    	ll res;cin>>res;
    	return res;
    }
    
    int main()
    {
    	ios::sync_with_stdio(false);
    	cin.tie(nullptr);
    	
        ready();
        for(auto v:pm) cout<<v<<endl; 
        int t;
        cin>>t;
        while(t--)
        {
        	ll ANS=1;
        	rep(k,0,21)
        	{
        		ll ans=ask(test[k]),cnt;
        		for(auto v:pm){
        			cnt=0;
        			while(ans%v==0) cnt++,ans/=v; 
        			ANS*=(cnt+1);
    			}
    		}
    		cout<<"! "<<ANS*2<<endl;
    	}
    } 
    
  • 相关阅读:
    怎样使用Secure CRT查看vcenter和esxi主机的日志文件(转)
    Linux下如何查看系统启动时间和运行时间
    Java使用线程并发库模拟弹夹装弹以及发射子弹的过程
    使用Java线程并发库实现两个线程交替打印的线程题
    Android Exception Type "share_dialog_title" is not translated in en, zh-rTW strings
    Java JDK1.5、1.6、1.7新特性整理
    Java 中long类型转换成为int类型时可能会出错的地方
    Java 将任意数组的任意两个位置的数据进行交换
    Java设置以及获取JavaBean私有属性进阶
    Java使用PropertyDescriptor获取实体类中私有属性的值,并给私有属性赋值
  • 原文地址:https://www.cnblogs.com/17134h/p/12927549.html
Copyright © 2011-2022 走看看