首页 > 代码库 > UVa10036
UVa10036
一 题意描述:
给你N(1<=N<=10,000)个数字,你可以在它们之间的N-1个位置任意放“+”或“-”,放完之后,我们可以计算出表达式的值。 存不存在一种摆放方案使得最后表达式的值可以被K(1<=K<=100)整除。
二 思路分析:
1.基础知识巩固之负数除以正数的余数:
由带余除法,任何一个整数n都可以表示成
n=k*q+r 其中0<=r<q
这里的r就是n除以q的余数
通常记为
n≡r(mod q)
例如
-9=(-2)*5+1
则-9除以5的余数为1。为了保证余数为正,那对于一个负数s(s的绝对值小于k),要求它除以k的余数,那么我们可以用(s+k)%k求得余数。
2.如何引入dp?
我们用f[i][j]=1表示前i个数处理后所得余数为j(0<=J<K),如f[i-1][j]=1;
那么对于第i个数(不妨设为正,任何情况下都取该数的绝对值)而言,有两种选择+或者-。
对于+:处理第i个数后的余数为(j+abs(a[i])%k)%k.那么f[i][(j+abs(a[i])%k)%k]=true;
对于—:处理第i个数后的余数为(j-abs(a[i])%k+k)%k.那么f[i][(j-abs(a[i])%k+k)%k]=true;
如此往复,直到处理完最后一个数。
下面开始判断:如果f[n-1][0]=true,说明这种情况可以被整除,输出visiable.否则输出disvisable。
三 源码:
1 #include <iostream> 2 #include <fstream> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 using namespace std; 7 const int N = 10000 + 10; 8 const int K = 100 + 10; 9 bool f[N][K];10 int a[N];11 int main()12 {13 int n,k;14 int t;15 cin>>t;16 while(t--)17 {18 for(int i=0;i<n;i++)19 cin>>a[i];20 memset(f,false,sizeof(f));21 f[0][abs(a[0])%k]=true;22 for(int i=1;i<n;i++)23 {24 for(int j=0;j<k;j++)25 if(f[i-1][j])//如果上一次余数存在且为j26 {27 f[i][(j+abs(a[i])%k)%k]=true;//(a+b)%k的余数等于( a%k +b%k )%k.28 f[i][(j+k-abs(a[i])%k)%k]=true;//此处加k是为了避免余数为负值。29 }30 }31 if(f[n-1][0]) cout<<"Divisible"<<endl;32 else cout<<"Not divisible"<<endl;33 }34 return 0;35 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。