『日常训练』2020WFU个人积分赛第一场

  1. D - A 的 B 次方【快速幂】

    思路:快速幂

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5 + 5;
    ll qsm(ll a,ll b,int mod){
        ll ans = 1;
        while(b){
            if(b&1) ans = ans*a%mod;
            a = a*a%mod;
            b >>= 1;
        }
        return ans%mod;
    }
    int main(void) {
        ll a,b,m;
        cin >> a >> b >> m;
        cout<<qsm(a,b,m)<<endl;
        return 0;
    }
    
  2. C - 序列的第 k 个数【快速幂】

    思路:快速幂

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5 + 5;
    const int mod = 200907;
    ll ksm(ll a,ll b,int mod){
        ll ans = 1;
        while(b){
            if(b&1) ans = ans*a%mod;
            a = a*a%mod;
            b >>= 1;
        }
        return ans;
    }
    int main(void) {
        int t;
        cin >> t;
        while(t--){
            ll a,b,c,k;
            cin >> a >> b >> c >> k;
            if(2*b==a+c){
                ll ans = a%mod+((k-1)%mod*(b-a)%mod)%mod;
                cout<<ans%mod<<endl;
            }else{
                ll q = b/a;
                ll q1 = q-1;
                ll qk = ksm(q,k-1,mod);
                cout<<qk*a%mod<<endl;
            }
        }
        return 0;
    }
    
  3. A - String Problem【最短路】

    题意:小男孩Valera喜欢字符串。当它们是相同的时候,他会更喜欢它们。这就是为什么Valera会在空闲时间玩下面这个游戏。 他有两个由小写字母组成的字符串,根据游戏规则,Valera每次可以将其中一个字符串中的任何一个字母 A i A_i 变为 B i B_i ,但要支付 W i W_i 的代价。请你输出让两个字符串相同的最小代价,无解输出-1。

    思路:首先这道题要注意有坑点,就是不一定 A i A_i 变为 B i B_i ,可以 A i A_i 变为 C i C_i B i B_i 变为 C i C_i ,只要转换的代价小即可。无解的两种情况,字符串长度不一样; A i A_i 无法变成 B i B_i 。有解的情况就是一个Floyd最短路了。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 500 + 50;
    int mp[maxn][maxn];
    const int INF = 0x3f3f3f3f;
    int main(void) {
        string s;
        string t;
        cin >> s >> t;
        int n;
        cin >> n;
         for(int i = 0; i < 26; i++){
            for(int j = 0; j < 26; j++){
                if(i==j) mp[i][j] = 0;
                else mp[i][j] = INF;
            }
        }
        while(n--){
            char u,v;
            int w;
            cin >> u >> v >> w;
            u = u-'a';
            v = v-'a';
            mp[u][v] = min(mp[u][v],w);
        }   
        if(s.size()!=t.size()){
            cout<<-1<<endl;
            return 0;
        }
        for(int k = 0; k < 26; k++){
            for(int i = 0; i < 26; i++){
                for(int j = 0; j < 26; j++){
                    mp[i][j] = min(mp[i][j],mp[i][k]+mp[k][j]);
                }
            }
        }
        int ans = 0;
        int len = s.size();
        string anss = "";
        for(int i = 0; i < len; i++){
            if(s[i]==t[i]){
                anss += s[i];
            }
            else{
                int minn = INF;
                int u = s[i]-'a';
                int v = t[i]-'a';
                char tmp;
                for(int j = 0; j < 26; j++){
                    if(mp[u][j]+mp[v][j]<minn){
                        minn = mp[u][j]+mp[v][j];
                        tmp = j+'a';
                    }
                }
                if(minn==INF){
                    cout<<-1<<endl;
                    return 0;
                }
                anss += tmp;
                ans += minn;
            }
        }
        cout<<ans<<endl;
        cout<<anss<<endl;
        return 0;
    }
    
  4. B - Garland【线性DP】

    题意:有一个由1-n构成的数列,其中部分被删除(删除的元素由0代替),请用被删除的元素补全这个数列,使这个数列中相邻元素奇偶性不同的对数最少。

    思路:对比0-1背包,对于每个0,你都可以选择放一个奇数或者放一个偶数,当前状态是由前面的奇偶决定,类似于有向图DAG,所以dp。

    dp[i][j][k][2]

    第一个状态:每个数字的位置

    第二个状态:当前位置的奇数个数

    第三个状态:当前位置的偶数个数

    第四个状态:当前位置的是奇数还是偶数

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e2 + 10;
    int dp[maxn][maxn][maxn][2];
    int a[maxn];
    int main(void) {
    	int n;
    	cin >> n;
    	for(int i = 1; i <= n; i++) cin >> a[i];
    	memset(dp,0x3f,sizeof(dp));
    	int odd = n/2+n%2;
    	int even = n/2;
    	dp[0][odd][even][1] = dp[0][odd][even][0] = 0;
    	for(int i = 1; i <= n; i++){
    		for(int j = 0; j <= odd; j++){
    			for(int k = 0; k <= even; k++){
    				if(a[i]&&a[i]%2||a[i]==0){  //放奇数
    					dp[i][j][k][1] = min(dp[i][j][k][1],dp[i-1][j+1][k][0]+1);//这一个数的上一位是偶数。
    					dp[i][j][k][1] = min(dp[i][j][k][1],dp[i-1][j+1][k][1]);//这一个数的上一位是奇数。
    				}
    				if(a[i]&&a[i]%2==0||a[i]==0){//放偶数
    					dp[i][j][k][0] = min(dp[i][j][k][0],dp[i-1][j][k+1][0]);//这一个数的上一位是偶数。
    					dp[i][j][k][0] = min(dp[i][j][k][0],dp[i-1][j][k+1][1]+1);//这一个数的上一位是奇数。
    				}
    			}
    		}
    	}
    	cout<<min(dp[n][0][0][1],dp[n][0][0][0])<<endl;
    	return 0;
    }
    
发布了8 篇原创文章 · 获赞 4 · 访问量 1531

猜你喜欢

转载自blog.csdn.net/wxd1233/article/details/105554943