p1044韩信点兵
Posted 邱宇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了p1044韩信点兵相关的知识,希望对你有一定的参考价值。
数论好难啊~~
嗯这两道题看似题号、数据范围差的很多,其实有一些共通之处。
先来看一下韩信点兵:
作为循环语句和判断语句的入门题,相信看我博客的肯定都会。
#include<iostream> using namespace std; int a,b,c,i; int main() { cin>>a>>b>>c; for(i=7+c;i<=100;i=i+7) { if((i%3==a)&&(i%5==b)&&(i>=10)&&(i<=100)) { cout<<i<<endl; return 0; } } cout<<"No answer"<<endl; return 0; }
下面来介绍一下直接算答案的强方法了。
ans需要满足三个条件%3==a、%5==b,%7==c;
那能不能构造出三个数,分别满足一个其中条件并且是另外两个数的公倍数?(这句话是本篇中最重要的话了,其他都是废话)
比如满足第一个条件的数要求为5和7的倍数,也就是35的倍数。还要%3==a,现在35%3已经等于2了,难道要35*a/2?(我知道a只可能等1 2)不如往后找一找,说不定有%3=1的好数。然后70就是了,很棒。那第一个数就是70*a了。
然后由于21%5==1,15%7==1,刚好。那么最后答案就是(70*a+21*b+15*c)%105。
本题中要求10到100之间的,加个判断就行。
1 #include<iostream> 2 using namespace std; 3 int a,b,c,ans; 4 int main() 5 { 6 cin>>a>>b>>c; 7 ans=(70*a+21*b+15*c)%105; 8 if(ans>=10&&ans<=100) cout<<ans; 9 else cout<<"No answer"<<endl; 10 return 0; 11 }
这道题的思想再推广一点会怎么样呢?那就是p1898了。
看不懂题解怎么办啊?没关系,往下看。
我们先处理出所有的a的累乘sum(应该不是sum吧但是我不知道用什么),对每个数找出sum/a[i]的倍数中%a[i]==1的,乘对应的b[i]是满足第i个条件的数。全部相加后对sum取余即为所求。\\
果然还是看不懂就对着代码看.
这个代码的复杂度好迷啊...如果要写的话还是学一下exgcd吧(18/12/10);
#include <cstdio> #include <iostream> #include <cmath> #include <string> #include <cstring> #include <algorithm> using namespace std; int i,f; long long wyt(long long x,long long y,long long z) { if(y==1)return 0; for(f=0;;f++) if(x*f%y==1)break; return f*x*z; } long long ans,sum=1; int n; long long a[11],b[11]; int main() { //freopen("123.in","r",stdin); //freopen("123.out","w",stdout); cin>>n; for(i=1;i<=n;i++) { cin>>a[i]>>b[i]; sum*=a[i]; } for(i=1;i<=n;i++) { ans+=wyt(sum/a[i],a[i],b[i]); } cout<<ans%sum; }
由于数较少,就不用快读了哈。
以上是关于p1044韩信点兵的主要内容,如果未能解决你的问题,请参考以下文章