加载中...

表达式 常和取模一起

贝茜的复仇dfs

贝茜给了约翰一个表达式 (B+E+S+S+I+E)(G+O+E+S)(M+O+O),其中包含七个变量 B,E,S,I,G,O,M(O 是变量,不是零)。
对于每个变量,她给约翰一个列表,表中包含该变量可采用的最多 20 个整数值。
她要求约翰计算,共有多少种给变量赋值的方法可以使得表达式的计算结果为偶数

解:因为最终只会看奇偶性,所以只看mod的结果。
为了方便表述,我们将 (B+2E+2S+I)(B+2E+2S+I) 称为第一项,(G+O+E+S)(G+O+E+S) 称为第二项,(M+2O)(M+2O) 称为第三项
用到引理:
偶数 + 奇数 = 奇数
偶数 + 偶数 = 偶数
奇数 * 奇数 = 奇数
偶数 * 奇数 = 偶数

因此只跟二进制的最后一位有关

有(ab)mod2=amod2amod2所以可以拆开 方案从20的7次方变成2的7次方 可以枚举

化简发现(B + I), (G + O + E + S), (M)
只要满足 B + I,或者 G + O + E + S 或者 M 其中任意一个为偶数,则答案为偶数

通过搜索将这些情况找出来

int ans;
//mp1存每一个字母奇数的个数,mp2存每一个字母偶数的个数,a存每一个字母的枚举为奇数还是偶数
map<char, int> mp1, mp2, a;
string s = "BESIGOM";//字母顺序无所谓,全部表示出来就行
void dfs(int u, int x){//x递归答案
    if(u == 7){
        if((a['B'] + a['I']) % 2 && (a['G'] + a['O'] + a['E'] + a['S']) % 2 && a['M'] % 2) return;
        ans += x;//全局变量表示答案
        return;
    }
    char ch = s[u];//代表一个字母
    a[ch] = 1, dfs(u + 1, x * mp1[ch]);//枚举ch为奇数的情况,累乘答案
    a[ch] = 2, dfs(u + 1, x * mp2[ch]);//枚举ch为偶数的情况,累乘答案
}
int main(){
    int n; cin >> n;
    for(int i = 0; i < n; i++){
        char c; int x; cin >> c >> x;
        if(x % 2) mp1[c]++;//字母C中奇数的个数
        else mp2[c]++;//字母C中偶数的个数
    }
    dfs(0, 1);
    cout << ans;
    return 0;
}


合适数对(暴力枚举解方程)

给出a,b,n 求满足 ax+by=n 的非负整数x,y指
且a,b,n范围小于等于 1000
因为###限制条件 给出了很多,x,y必须》=0 所以 x,y小于等于一千 因此可以 0-1000枚举x,y

int main(){

  for(int x=0;x*a<=n&&x<1000;x++){//x*a<=n防止y变成负数
      if((x-a*x)%b==0){//把y放到一边,如果能整除说明找到了
       int y=(n-a*x)/b;
        cout<<"yes";
        cou<<x<<y;
        return 0;
        }
       
  }
  //到了这里说明找不到
  cout<<no;
}

最小结果 dfs

四个操作数 三个操作符要么是*和+ 按照每个操作符顺序从四个操作数选出一个个算 (不同于普通表达式) 要求表达式最终生成 最小 的数

容易想到会消除乘法两边 再算加法最后变成一个数
//直接新建一个容器 用这个容器进行下一步递归
//i,j用于选择数据
坑点//坑点有0
//不能交换操作符
//会爆int
//爆搜
直接dfs 画出递归搜索树 发现情况小 直接爆搜

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#define int long long
using namespace std;

char c[3];
int ans=1e18;

void dfs(vector<int> v,int u ){
    if(v.size()==1){
        ans=min(ans ,v[0]); return ;//只剩一个数,递归终点
    } 
    for (int i = 0; i < v.size(); i ++ ){
        for (int j = i+1; j < v.size(); j ++ ){//i,j用于选择数据
            vector<int> t;//直接新建一个容器 用这个容器进行下一步递归
            for (int k = 0; k < v.size(); k ++ ){
                if(k!=i&&k!=j) t.push_back(v[k]);//容器只放入没有选过的数字
                
            }
            if(c[u]=='*') t.push_back(v[i]*v[j]);
            else t.push_back(v[i]+v[j]);
            
            dfs(t,u+1);
        }
    }
}
signed main(){vector<int>a(4) ;
    for (int i = 0; i < 4; i ++ ) cin>>a[i];
    for (int i = 0; i < 3; i ++ ) cin>>c[i];
    
    dfs(a,0);
    cout << ans;
    
    
    return 0;
}

四平方和

先枚举大的数c 0到sqrt(n) 而d从c到dd+cc<=n;
找到s
之后同样枚举 a和b 再最后就可以达到n-aa-bb存在就 直接输出 保证字典序最小


int main()
{
    int n;cin>>n;
    memset(C, -1, sizeof C);
    for (int c = 0; c*c <=n ; c ++ ){
        for (int d = c; d*d+c*c <= n; d ++ ){
            int s=c*c+d*d;
            if(C[s]==-1 )
            C[s]=c ,D[s]=d;
        }
    }
    for (int a = 0; a*a <= n; a ++ ){
        for (int b =a ; b*b+a*a <= n; b ++ ){
            int s=n-a*a-b*b;
            if(C[s]!=-1 ){
                cout <<a <<" "<<b<<" "<<C[s]<<" "<<D[s]<<endl ;
            
                return 0;    
            }
        }
    }
    
    return 0;
}
posted @ 2022-01-26 23:00  liang302  阅读(34)  评论(0编辑  收藏  举报