牛客网暑期ACM多校训练营(第四场)

题目:https://www.nowcoder.com/acm/contest/142#question

A题

2生1 1生0 0消除。问要多少次。

这个题目肯定是个规律题。首先暴力一下就行了。然后就可以发现规律,012和前面消除的次数关系。

然后用dfs,进行搜索。然后要用欧拉函数,关于指数循环节了。然后预处理一下欧拉函数就可以了。

#include<bits/stdc++.h>
 
using namespace std;
typedef long long ll;
map<ll,ll> m;
    string s;
ll ph(ll x){
    ll res=x,a=x;
    for(ll i=2;i*i<=x;i++){
        if(a%i==0) {
        res=res/i*(i-1);
        while(a%i==0) a/=i;
        }
    }
    if(a>1) res=res/a*(a-1);
    return res;
}
ll poww(ll a,ll b,ll mod){
    ll ans=1;
    while(b){
        if(b&1) ans=(ans*a)%mod;
        a=(a*a)%mod;
        b>>=1;
    }
    return ans;
}
ll dfs(ll i,ll mod){
    if(i==0) return 0;
    else if(s[i]=='0') return (dfs(i-1,mod)+1)%mod;
    else if(s[i]=='2') return ((3ll*poww(2,dfs(i-1,m[mod])+1,mod)-3)%mod+mod)%mod;
    else return (2*dfs(i-1,mod)+2)%mod;
}
 
int main(){
    ll t,i=1000000007;
    cin>>t;
    for(;i!=1;i=m[i]){
            m[i]=ph(i);
		}
        m[1]=1;
    while(t--){
        cin>>s;
        s="1"+s;
        int len=s.length();
        printf("%lld\n",dfs(len-1,1000000007));
    }
    return 0;
}

F题

其实就是判断去掉中心某一块,这个图形对不对称。其实就是直接暴力一下,然后优化一点就可以了吧。

#include<bits/stdc++.h>
#define INF 1e18
#define inf 1e9
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:b
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define IOS ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std ;
typedef long long ll;
typedef unsigned long long ull;
const int _max = 2005;
char mp[_max][_max];

int main(){
	IOS;
	int t;
	cin>>t;
	while(t--){
		int n,m,ret = 0;
		bool k = 1;
		cin>>n>>m;
		for(int i = 1 ; i <= n ; i++)
			for(int j = 1 ; j <= m ; j++)
			cin>>mp[i][j];
		int x=n/2,y=m/2;
		for(int i = 1; i <= n/2; i++) {
            for(int j = 1; j <= m/2; j++) {
                if((mp[i][j] != mp[i][m-j+1]) || (mp[n-i+1][j] != mp[n-i+1][m-j+1]) || (mp[i][j] != mp[n-i+1][j])){
                    x = min(x,i);
                    y = min(y,j);
                }
 
            }
        }
		cout<<(x-1)*(y-1)<<endl;
	}
	return 0;
}

G题

n个数,删m个数,使得剩下的里面众数为最大的。

可以先预处理一下,若要该数最大最少需要删多少个。然后看看是否满足要求,如果小于肯定是不可以,如果大于就OK,其他可以随便删。

#include<bits/stdc++.h>
#define INF 1e18
#define inf 1e9
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:b
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define IOS ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std ;
typedef long long ll;
typedef unsigned long long ull;

const int _max = 1e5+50;
map<int,int> mp;
int a[_max];
int main(){
	int t;
	cin>>t;
	while(t--){
		mp.clear();
		int n,m,val,len = 0;
		int ret = -1;
		cin>>n>>m;
		for(int i = 1 ; i <= n ; i++){
			cin>>val;
			if(!mp[val]) a[++len] = val;
			mp[val]++;
		}
		sort(a,a+len+1);
		for(int i = len ; i >= 1 ; i--){
			int v = 0,p = mp[a[i]];
			for(int j = 1 ; j <= len ; j++){
				if(i == j) continue;
				if(mp[a[j]] >=  p){
					v += (mp[a[j]]-p+1);
					if(v > m) break;
				}
			}
			if(v <= m){
				ret = a[i];
				break;
			}
		}
		cout<<ret<<endl;
	}
	return 0;
}

D题

要求n的矩阵行列不相等。所以需要组合出2n个数。

从2*2开始推,然后向外扩展。发现,如果3*3时,无法保留2*2所得的结果,那么就肯定无法组合出2n个。

然后就很容易知道,是需要每次扩展2行2列。然后并且保证保留原数,就是1 1 -1 -1这样的组合。

比如

1 0

1 -1  

变成

x x 1 1

x x -1 -1

1 -1 1 0

1 -1 1 -1

然后就是要想办法求出x,因为又是一个2*2。猜测为一开始的2*2矩阵,发现可以/wx(果然全靠蒙就可以了)

就得到规律了。所以我们只需要先初始化一个200*200的矩阵。然后判断一下n,如果是奇数就不可以,否则就可以喽。

#include<bits/stdc++.h>
#define PI 3.1415926
#define INF 1e18
#define inf 1e9
#define IOS ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std ;
typedef long long ll;
typedef unsigned long long ull;
const ll _max = 205;
int mp[_max][_max];
void solve(){
	int n = 200;
	for(int i = 1 ; i <= n ; i+=2){
		mp[i][i] = 1; mp[i][i+1] = 0;
		mp[i+1][i] = 1 ; mp[i+1][i+1] = -1;
		int val = 1;
		for(int j = 1 ; j < i ; j++){
			mp[i][j] = val;
			mp[i+1][j] = val;
			mp[j][i] = val;
			mp[j][i+1] = val;
			val*=-1;
		}
	}	
}
int main(){
	solve();
	int t,n;
	cin>>t;
	while(t--){
		cin>>n;
		if(n&1) cout<<"impossible"<<endl;
		else{
			cout<<"possible"<<endl;	
			for(int i = 1 ; i <= n ; i++){ 
				for(int j = 1 ; j <= n ; j++){
					cout<<mp[i][j]<<' ';
				}
				cout<<endl;
			} 
		}
		
	}
	
	return 0;
}

补题:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值