week15

div2 每日一题

305 删删

  • 暴力

  • #include<bits/stdc++.h>
    using namespace std;
    int t;
    int main()
    {
    	cin.tie(0);
    	cout.tie(0);
    	cin>>t;
    	while(t--)
    	{
    		int n,ans=1e9,sum=0;
    		string s;
    		cin>>n>>s;
    		for(char i='a';i<='z';i++)
    		{
    			bool flag=true;
    			int l=0,r=n-1,sum=0;
    			while(l<r)
    			{
    				if(s[l]==s[r]) l++,r--;
    				else
    				{
    					if(s[l]==i) l++,sum++;
    					else if(s[r]==i) r--,sum++;
    					else
    					{
    						flag=false;
    						break;
    					}
    				}
    			}
    			if(flag)
    			ans=min(ans,sum);
    		}
    		if(ans==1e9) cout<<"-1"<<endl;
    		else cout<<ans<<endl;
    	}
    	return 0;
    }
    

    306 快快变大(区间dp)

  • dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+cost)

    cost指代把dp[i][k] 和 dp[k+1][j] 的两个区间合并起来的花费

  • 注意i k合并后的数值要预处理不然可能会超时

  • #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int mx=1e3+5;
    const int INF=0x3f3f3f3f;
    ll n,t=0;
    ll f[301][301],aa[301][301];
    int main()
    {
        cin.tie(0);
        cout.tie(0);
        cin>>n;
        ll a[n+1];
        for(int i=1;i<=n;i++)
        {
            scanf("%ld",&a[i]);
            f[i][i]=0;
            aa[i][i-1]=1;
        }
        for(int i=2;i<=n;i++)
        {
            f[i-1][i]=pow(a[i-1]-a[i],2);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=i;j<=n;j++)
            {
                aa[i][j]=aa[i][j-1]*a[j]%1000003;
            }
        }
        for(int l=2;l<=n;l++)
        {
            for(int i=1;i+l-1<=n;i++)
            {
                int j=i+l-1;
                for(int k=i;k<j;k++)
                {
                    ll tp3=pow(aa[i][k]-aa[k+1][j],2);
                    f[i][j]=max(f[i][k]+f[k+1][j]+tp3,f[i][j]);
                }
            }
        }
        printf("%ld",f[1][n]);
    }
    

    307饿饿 饭饭2
    题目描述
    接着《饿饿 饭饭》 的故事,在两天后,食堂的工作人员回来了,整个食堂又回到了原来井井有条的状态。

    两个月后,由于天气越来越热,大家的胃口越来越小了,作为食堂管理员的CC非常担心孩子们的身体健康,所以他决定开展一个活动来调动孩子们吃饭的积极性,顺便考验一下孩子们的数学水平。活动内容如下:

    先让每一个孩子都抽一个球,每一个球上有一个数字, 然后给这个孩子n个数字,每一个孩子都有无数次操作机会,每一次都会选中一个数将它乘上2,或者乘上3,请问这个孩子可以通过上面的操作将这n个数都变成相同的吗?

    如果回答正确,这个回答正确的孩子就可以得到一份免费的午餐,但是这对于孩子们来说是在是太困难了,但是他们都想吃到免费的午餐,所以他们都想请你告诉他们正确的答案,让他们都迟到免费的午餐。

    输入格式
    第1行给定一个数T,表示有T个小孩子请你告诉他正确的答案。

    第2到T+1行,第1个数是每个孩子抽到的数字n,第2到n+1个数是对应的n个数字。

    输出格式
    如果可以变成相同的,输出YES。如果不能变成相同的,输出NO。

    数据规模
    1 ≤ T ≤ 100 , 1 ≤ n ≤ 2 × 1 0 5 , 1 ≤ a i ≤ 1 0 9 1≤T≤100,1≤n≤2×10^5,1≤a_i≤10^91≤T≤100,1≤n≤2×10 
    5
     ,1≤a 
    i
    ​    
     ≤10 
    9
     
    数据保证∑ i = 1 T n ≤ 2 × 1 0 5 ∑^T_{i=1}n≤2×10^5∑ 
    i=1
    T
    ​    
     n≤2×10 
    5
     

    样例输入
    2
    4 75 150 75 50
    3 100 150 250
    1
    2
    3
    样例输出
    YES
    NO
    1
    2
    思路
    先找到这n个数的最大公因数,接着除以最大公因数,接下来判断每个数是否能被2和3整除到1,但凡有一个未除以到1,则答案为NO

    #include <bits/stdc++.h>
    using namespace std;
    const int Max = 2e5+5;
    int t,n;
    long long a[Max];
    int main(){
        cin >> t;
        for(int i = 1; i <= t; i++){
            cin >> n;
            memset(a,0,sizeof(a));
            long long gcd;
            for(int j = 1; j <= n; j++)  cin >> a[j];
            gcd = a[1];  //cout << a[1] << endl;
            for(int j = 2; j <= n; j++){
                gcd=__gcd(gcd,a[j]);
                //cout << gcd << endl;
            }
            //cout << gcd << endl;
            for(int j = 1; j <= n; j++){
                a[j]/=gcd;
                while(a[j]%3==0 || a[j]%2==0){
                    if(a[j]%3==0) a[j]/=3;
                    if(a[j]%2==0) a[j]/=2;
                }
            }
            int flag=0;
            for(int j = 1; j <= n; j++){
                if(a[j]!=1) {
                    flag=1;
                    break;
                }
            }
            if(flag==0)  cout << "YES" << endl;
            else  cout << "NO" << endl;
        }
    }
    

401子串分值和

思路
对于样题:
对于每个子串来说,字母第一次出现且被包含,包含其的子串的F必然会算上该字母,即+1,每个包含该字母的子串F值都要算上该字母,故所有字母第一次出现包含其的子串数和即为答案
而我们之前做到过一道类似的,包含字母x的字串总个数与该字母左右个数有关,即l+r+l*r+1
此题我们用map来记录上一个字母出现的位置,注意s从0开始,但是我们记录的时候要加1

#include <bits/stdc++.h>
using namespace std; 
string s;
map<char, int> q;
int main(){
    cin >> s;
    long long ans = 0;
    int len = s.length();
    for(int i = 1; i <= len; i++){
        //cout << 1+len-i+i-q[s[i-1]]-1+(i-q[s[i-1]]-1)*(len-i) << endl;
        ans += 1+len-i+i-q[s[i-1]]-1+(i-q[s[i-1]]-1)*(len-i);
        q[s[i-1]]=i;
        //cout << i-1 << " ";
        //cout << ans << " ";
       // cout << s[i-1] << " ";
    }
    cout << ans << endl;
}

402蒟蒻

思路

直接map,可以去重的同时选取最小的

#include <bits/stdc++.h>
using namespace std;
map<int, int> q1;
map<int, int> q2;
int n;
int main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        int op,w,t;
        cin >> op;
        if(op==1){
            cin >> w >> t;
            if(q1.count(w)==0 && q2.count(t)==0){
                q1[w]=t;
                q2[t]=w;
            }
        }
        else if(op==2){
            q2.erase(q1.begin()->second);
            q1.erase(q1.begin());
        }
        else if(op==3){
            q1.erase(q2.begin()->second);
            q2.erase(q2.begin());
        }
    }
    int ans = 0;
        for(auto x:q1){
            ans+=x.first;
        }
        cout << ans << endl;
}

403锦标赛

思路
升序排序,找最大的t使得∣ a t − a t − 1 ∣ > K |a_t−a_{t-1}|>K∣a t−at−1∣>K,则在t之前的所有小于a t a_ta  的数最终都会被淘汰掉,因为总可以找到一个数使得∣ a x − a ∣ > K |a_x-a|>K∣a 
x −a∣>K;
找到该数t之后,t~n即最终可能留下的数,即n-t+1个数
 

#include <bits/stdc++.h>
using namespace std;
const int Max = 1e5+5;
int n;
long long k;
long long a[Max];
int main(){
    cin >> n >> k;
    for(int i = 1; i <= n; i++) cin >> a[i];
    sort(a+1,a+n+1);
    int t=1;
    for(int i = 2; i <= n; i++){
        if(abs(a[i]-a[i-1])>k) t=i;
    }
    //cout <<t << endl;
    cout << n-t+1;
}

404可重排列

思路

dfs深搜

#include <bits/stdc++.h>
using namespace std;
const int Max = 1e5+5;
int vis[10];
int a[Max];
int n;
int num=0;
void print(){
    for(int i = 1; i <= num; i++){
        printf("%d ",a[i]);
    }
    //cout << endl;
    printf("\n");
}
void dfs(int s){
    if(s == num+1){
        print();
        return;
    }
    for(int i = 1; i <= 9; i++){
        if(vis[i]!=0){
            a[s]=i;
            vis[i]--;
            dfs(s+1);
            vis[i]++;
        }
    }
}
int main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        //cin >> vis[i];
        scanf("%d", &vis[i]);
        //cout << i << ":" << vis[i] << endl;
        num+=vis[i];
    }
    //cout << num << endl;
    dfs(1);
}

 405进制转换

思路

先转换为十进制,后做运算,再辗转相除逆置转换为m进制输出

#include <bits/stdc++.h>
using namespace std;
int n,m;
char x[200];
int d[200];
void ini(){
    int j = 0;
    for(char i='0'; i<='9'; i++,j++){
        x[j]=i;
        d[i]=j;
    }
    int k = 36, s= 10;
    for(char i = 'a', j = 'A'; i<='z'; i++,j++){
        x[k]=i;
        x[s]=j;
        d[j]=s;
        d[i]=k;
        k++; s++;
    }
}
int main(){
    cin >> n >> m;
    ini();
    long long ans=0;
    for(int i = 1; i <= n; i++){
        int t;
        string s;
        cin >> t >> s;
        int len = s.length();
        //cout << s << endl;
        for(int j = len-1; j>=0;j--){
            //cout << d[s[j]] << endl;
            ans+=d[s[j]]*pow(t,len-1-j);
            //cout << ans << endl;
        }
    }
    //cout << ans << endl;
    string mj;
    do{
        mj+=x[ans%m];
        ans/=m;
    }while(ans!=0);
    reverse(mj.begin(), mj.end());
    cout << mj;
}

406循环子串 

 思路
若P r e v e r s e P_{reverse}P 
reverse
​    
 是P的循环字串,则P中的任何一个字串经过右移都可以变成P r e v e r s e P_{reverse}P 
reverse
​    
 中的一个字串,也就是P的一个字串。那么我们只需要判断P r e v e r s e P_{reverse}P 
reverse
​    
 是不是P的循环字串,如果是的话,我们就输出"YES",否则就输出"NO"
 

#include <bits/stdc++.h>
using namespace std;
int t,n;
string s;
int main(){
    cin >> t;
    for(int i = 1; i <= t; i++){
        cin >> n >> s;
        string ss = s+s;
        reverse(s.begin(), s.end());
        int flag = 0;
        for(int j = 0; j <= n; j++){
            string sub = ss.substr(j,n);
            if(sub == s){
                flag = 1;
                break;
            }
        }
        if(flag==1)  cout << "YES" << endl;
        else  cout << "NO" << endl;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值