http://codeforces.com/contest/822
1 是阶乘的gcd,所以直接找最小的就好了qwq
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{ int m,n;
scanf("%d%d",&m,&n);
if(n>m) swap(m,n);
ll a=1;
for(int i=2;i<=n;i++)
a*=1ll*i;
printf("%lld\n",a);
return 0;
}
2 给定一个字符串 x ,和母串y。
x可以改变任意字符为? ,?可以被当做任意字符,问你最少需要改变多少个x的字母,能够使x是y的子串。
长度都不到1000,直接暴力匹配,压位保存位置。(其实只记录开头也行)
#include <bits/stdc++.h>
using namespace std;
int main()
{ int m,n;
string a,b;
bitset<1005>z2;
cin>>m>>n;
cin>>a;
cin>>b;
int ans=1005;
for(int i=0;i<b.length()-m+1;i++){
bitset<1005>z1;
int sum=0;
for(int j=i,x=0;j<m+i;j++,x++){
if(b[j]!=a[x]){
sum++;
z1.set(x);
}
}
if(sum<ans){
ans=sum;
z2=z1;
}
}
printf("%d\n",ans);
int flag=true;
for(int i=0;i<1000;i++){
if(z2.test(i)){
if(flag)
{printf("%d",i+1),flag=false;}
else
printf(" %d",i+1);
}
}
cout<<endl;
return 0;
}
3 思维题。有大约三种写法。
1种是思维,一种是二分,第三dp?
思维大致就是保存第一个值,放到一个map里,然后找第二个时,维护一个最小值就行,但是有一点比较重要的是,map设置的时间要对,因为两个区间不能重叠,相等都不可以。
第一种思路是 枚举左区间,处理完 在做map,这样map只给后面的l用,不会重叠
第二种思路是 压位两种区间,第二种就是用来计算map的,并且第二种不会给第一种用,因为第二种在第一种后面。只能给之后得用。(注意反转)
#include <bits/stdc++.h>
using namespace std;
/*这道题,估计有三种方法
1 暴力求解。保留一个结构体,保存他的 左右和价值。
然后 存的时候,把数组下标当成他的左界,
遍历l,然后寻找 最好的解。
(保存一个他的第一次到达的极值。)
*/
typedef long long ll;
const int maxn=2e5+10;
vector<pair<int,int> >q[maxn];
vector<pair<int,int> >v[maxn];
map<int,int>mp;
int main()
{ int m,n;
int l,r,cost;
scanf("%d%d",&m,&n);
for(int i=0;i<m;i++){
scanf("%d%d%d",&l,&r,&cost);
q[l].push_back(make_pair(r,cost));
}
ll ans=2e9+1000;
for(int i=1;i<=2e5+1;i++){//枚举左区间
for(int j=0;j<q[i].size();j++){
int rig=q[i][j].first;
int tim=q[i][j].first-i+1;
int cos=q[i][j].second;
if(tim>n)
continue;
if(mp[n-tim]){
ans=min(ans,1ll*(cos+mp[n-tim]));
}
v[rig].push_back(make_pair(tim,cos));
}
for(int x=0;x<v[i].size();x++){
int tim=v[i][x].first;//时间
int cos=v[i][x].second;//花费
if(!mp[tim]||mp[tim]>cos)
mp[tim]=cos;
}
}
if(ans==(2e9+1000))
puts("-1");
else
printf("%lld\n",ans);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
struct Node
{ int l,r;
int cos,type;
Node(){};
Node(int _a,int _b,int _c,int _d){l=_a;r=_b;cos=_c;type=_d;};
};
vector<Node>v;
bool cmp2(Node a,Node b){
if(a.l==b.l)
return a.type<b.type;
return a.l<b.l;
}
map<int,int>mp;
typedef long long ll;
int main()
{ int m,n,a,b,c;
scanf("%d%d",&m,&n);
for(int i=0;i<m;i++){
scanf("%d%d%d",&a,&b,&c);
v.push_back(Node(a,b,c,-1));
v.push_back(Node(b,a,c,1));
}
sort(v.begin(),v.end(),cmp2);
ll ans=2e9+1000;
for(int i=0;i<v.size();i++){
if(v[i].type==-1){
int len=v[i].r-v[i].l+1;
if(len>=n||mp[n-len]==0) continue;
ans=min(ans,1ll*(mp[n-len]+v[i].cos));
}
else {
int len=v[i].l-v[i].r+1;
if(!mp[len]||(mp[len]>v[i].cos))
mp[len]=v[i].cos;
}
}
if(ans==2e9+1000)
puts("-1");
else
printf("%lld\n",ans);
return 0;
}
4 没思路,看的题解。
关键是搞不出来 怎么分配才能让总的比较次数最少。
后来发现,若有x个人,分的小组的人数应为x的最小质因子。
如果本身 就是质数,就直接计算。
有图为证
记住这个规律吧qwq
用欧拉筛,能够保存x的最小素因子。
用 quickpow 会超时。这里可以不用。。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=5000001;
ll prime[MAXN];//保存素数
bool vis[MAXN];//初始化
int mi[MAXN];
ll dp[MAXN];
const int mod=1e9+7;
ll quickpow(ll k,ll n){
ll m=k%mod;
ll ans=1;
while(n){
if(n&1) ans=(ans*m)%mod;
m=(m*m)%mod;
n>>=1;
}
//cout<<m<<" "<<n<<" "<<ans<<endl;
return ans%mod;
}
int Prime(int n)//范围
{
int cnt=0;
memset(vis,0,sizeof(vis));
for(int i=2;i<n;i++)
{
if(!vis[i]){
prime[cnt++]=i;//保存素数。
mi[i]=i;
}
for(int j=0;j<cnt&&i*prime[j]<n;j++)
{
vis[i*prime[j]]=1;//有vis的就是 和数。
mi[i*prime[j]]=prime[j];//记录当前这个数的 最小素因子。
if(i%prime[j]==0)//关键
break;
}
}
return cnt;//返回小于n的素数的个数
}
int main(){
int t,n,m;
Prime(MAXN);
for(int i=2;i<MAXN;i++){
dp[i]=(dp[i/mi[i]]+1ll*i*(mi[i]-1)/2)%mod;
}
//for(int i=1;i<=100;i++)
//cout<<dp[i]<<endl;
ll ans=0;
ll buf=1;
scanf("%d%d%d",&t,&n,&m);
for(int i=n;i<=m;i++){
//ans=(ans+(dp[i]%mod*quickpow(1ll*t,1ll*(i-n))))%mod;
//可以不用快速幂。范围太大 844079775 8212 4470298 比如这样,用快速幂反而会超时。。
// 用普通算法直接就算。
ans=(ans+dp[i]%mod*buf)%mod,
buf=buf*t%mod;
//cout<<ans<<endl;
}
printf("%lld\n",ans);
return 0;
}